mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Update API [skip ci]
This commit is contained in:
parent
beab635aba
commit
ee9815cff8
@ -30,11 +30,13 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface TONAccountState : NSObject
|
||||
|
||||
@property (nonatomic, readonly) bool isInitialized;
|
||||
@property (nonatomic, readonly) int64_t balance;
|
||||
@property (nonatomic, readonly) int32_t seqno;
|
||||
@property (nonatomic, strong, readonly) TONTransactionId * _Nullable lastTransactionId;
|
||||
@property (nonatomic, readonly) int64_t syncUtime;
|
||||
|
||||
- (instancetype)initWithBalance:(int64_t)balance seqno:(int32_t)seqno lastTransactionId:(TONTransactionId * _Nullable)lastTransactionId;
|
||||
- (instancetype)initWithIsInitialized:(bool)isInitialized balance:(int64_t)balance seqno:(int32_t)seqno lastTransactionId:(TONTransactionId * _Nullable)lastTransactionId syncUtime:(int64_t)syncUtime;
|
||||
|
||||
@end
|
||||
|
||||
|
@ -68,12 +68,14 @@ static TONTransactionMessage * _Nullable parseTransactionMessage(tonlib_api::obj
|
||||
|
||||
@implementation TONAccountState
|
||||
|
||||
- (instancetype)initWithBalance:(int64_t)balance seqno:(int32_t)seqno lastTransactionId:(TONTransactionId * _Nullable)lastTransactionId {
|
||||
- (instancetype)initWithIsInitialized:(bool)isInitialized balance:(int64_t)balance seqno:(int32_t)seqno lastTransactionId:(TONTransactionId * _Nullable)lastTransactionId syncUtime:(int64_t)syncUtime {
|
||||
self = [super init];
|
||||
if (self != nil) {
|
||||
_isInitialized = isInitialized;
|
||||
_balance = balance;
|
||||
_seqno = seqno;
|
||||
_lastTransactionId = lastTransactionId;
|
||||
_syncUtime = syncUtime;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@ -398,8 +400,11 @@ typedef enum {
|
||||
[subscriber putError:[[TONError alloc] initWithText:[[NSString alloc] initWithUTF8String:error->message_.c_str()]]];
|
||||
} else if (object->get_id() == tonlib_api::testGiver_accountState::ID) {
|
||||
auto result = tonlib_api::move_object_as<tonlib_api::testGiver_accountState>(object);
|
||||
TONTransactionId *lastTransactionId = [[TONTransactionId alloc] initWithLt:result->last_transaction_id_->lt_ transactionHash:makeData(result->last_transaction_id_->hash_)];
|
||||
[subscriber putNext:[[TONAccountState alloc] initWithBalance:result->balance_ seqno:result->seqno_ lastTransactionId:lastTransactionId]];
|
||||
TONTransactionId *lastTransactionId = nil;
|
||||
if (result->last_transaction_id_ != nullptr) {
|
||||
lastTransactionId = [[TONTransactionId alloc] initWithLt:result->last_transaction_id_->lt_ transactionHash:makeData(result->last_transaction_id_->hash_)];
|
||||
}
|
||||
[subscriber putNext:[[TONAccountState alloc] initWithIsInitialized:true balance:result->balance_ seqno:result->seqno_ lastTransactionId:lastTransactionId syncUtime:result->sync_utime_]];
|
||||
[subscriber putCompletion];
|
||||
} else {
|
||||
assert(false);
|
||||
@ -478,17 +483,27 @@ typedef enum {
|
||||
[subscriber putError:[[TONError alloc] initWithText:[[NSString alloc] initWithUTF8String:error->message_.c_str()]]];
|
||||
} else if (object->get_id() == tonlib_api::generic_accountStateUninited::ID) {
|
||||
auto result = tonlib_api::move_object_as<tonlib_api::generic_accountStateUninited>(object);
|
||||
[subscriber putNext:[[TONAccountState alloc] initWithBalance:result->account_state_->balance_ seqno:-1 lastTransactionId:nil]];
|
||||
TONTransactionId *lastTransactionId = nil;
|
||||
if (result->account_state_->last_transaction_id_ != nullptr) {
|
||||
lastTransactionId = [[TONTransactionId alloc] initWithLt:result->account_state_->last_transaction_id_->lt_ transactionHash:makeData(result->account_state_->last_transaction_id_->hash_)];
|
||||
}
|
||||
[subscriber putNext:[[TONAccountState alloc] initWithIsInitialized:false balance:result->account_state_->balance_ seqno:-1 lastTransactionId:lastTransactionId syncUtime:result->account_state_->sync_utime_]];
|
||||
[subscriber putCompletion];
|
||||
} else if (object->get_id() == tonlib_api::generic_accountStateTestWallet::ID) {
|
||||
auto result = tonlib_api::move_object_as<tonlib_api::generic_accountStateTestWallet>(object);
|
||||
TONTransactionId *lastTransactionId = [[TONTransactionId alloc] initWithLt:result->account_state_->last_transaction_id_->lt_ transactionHash:makeData(result->account_state_->last_transaction_id_->hash_)];
|
||||
[subscriber putNext:[[TONAccountState alloc] initWithBalance:result->account_state_->balance_ seqno:result->account_state_->seqno_ lastTransactionId:lastTransactionId]];
|
||||
TONTransactionId *lastTransactionId = nil;
|
||||
if (result->account_state_->last_transaction_id_ != nullptr) {
|
||||
lastTransactionId = [[TONTransactionId alloc] initWithLt:result->account_state_->last_transaction_id_->lt_ transactionHash:makeData(result->account_state_->last_transaction_id_->hash_)];
|
||||
}
|
||||
[subscriber putNext:[[TONAccountState alloc] initWithIsInitialized:true balance:result->account_state_->balance_ seqno:result->account_state_->seqno_ lastTransactionId:lastTransactionId syncUtime:result->account_state_->sync_utime_]];
|
||||
[subscriber putCompletion];
|
||||
} else if (object->get_id() == tonlib_api::generic_accountStateTestGiver::ID) {
|
||||
auto result = tonlib_api::move_object_as<tonlib_api::generic_accountStateTestGiver>(object);
|
||||
TONTransactionId *lastTransactionId = [[TONTransactionId alloc] initWithLt:result->account_state_->last_transaction_id_->lt_ transactionHash:makeData(result->account_state_->last_transaction_id_->hash_)];
|
||||
[subscriber putNext:[[TONAccountState alloc] initWithBalance:result->account_state_->balance_ seqno:result->account_state_->seqno_ lastTransactionId:lastTransactionId]];
|
||||
TONTransactionId *lastTransactionId = nil;
|
||||
if (result->account_state_->last_transaction_id_ != nullptr) {
|
||||
lastTransactionId = [[TONTransactionId alloc] initWithLt:result->account_state_->last_transaction_id_->lt_ transactionHash:makeData(result->account_state_->last_transaction_id_->hash_)];
|
||||
}
|
||||
[subscriber putNext:[[TONAccountState alloc] initWithIsInitialized:true balance:result->account_state_->balance_ seqno:result->account_state_->seqno_ lastTransactionId:lastTransactionId syncUtime:result->account_state_->sync_utime_]];
|
||||
[subscriber putCompletion];
|
||||
} else {
|
||||
assert(false);
|
||||
|
@ -508,7 +508,7 @@ public final class MediaBox {
|
||||
let fetchResource = self.wrappedFetchResource.get()
|
||||
let fetchedDisposable = fileContext.fetched(range: Int32(range.lowerBound) ..< Int32(range.upperBound), priority: priority, fetch: { intervals in
|
||||
return fetchResource
|
||||
|> introduceError(MediaResourceDataFetchError.self)
|
||||
|> castError(MediaResourceDataFetchError.self)
|
||||
|> mapToSignal { fetch in
|
||||
return fetch(resource, intervals, parameters)
|
||||
}
|
||||
@ -621,7 +621,7 @@ public final class MediaBox {
|
||||
let fetchResource = self.wrappedFetchResource.get()
|
||||
let fetchedDisposable = fileContext.fetchedFullRange(fetch: { ranges in
|
||||
return fetchResource
|
||||
|> introduceError(MediaResourceDataFetchError.self)
|
||||
|> castError(MediaResourceDataFetchError.self)
|
||||
|> mapToSignal { fetch in
|
||||
return fetch(resource, ranges, parameters)
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ public func mapError<T, E, R>(_ f: @escaping(E) -> R) -> (Signal<T, E>) -> Signa
|
||||
}
|
||||
}
|
||||
|
||||
public func introduceError<T, E>(_ type: E.Type) -> (Signal<T, NoError>) -> Signal<T, E> {
|
||||
public func castError<T, E>(_ type: E.Type) -> (Signal<T, NoError>) -> Signal<T, E> {
|
||||
return { signal in
|
||||
return Signal<T, E> { subscriber in
|
||||
return signal.start(next: { next in
|
||||
|
@ -219,7 +219,7 @@ public func addChannelMembers(account: Account, peerId: PeerId, memberIds: [Peer
|
||||
}
|
||||
|
||||
}
|
||||
|> introduceError(AddChannelMemberError.self)
|
||||
|> castError(AddChannelMemberError.self)
|
||||
|
||||
return signal
|
||||
|> switchToLatest
|
||||
|
@ -468,12 +468,12 @@ public func signUpWithName(accountManager: AccountManager, account: Unauthorized
|
||||
initializedAppSettingsAfterLogin(transaction: transaction, appVersion: account.networkArguments.appVersion, syncContacts: syncContacts)
|
||||
transaction.setState(state)
|
||||
}
|
||||
|> introduceError(SignUpError.self)
|
||||
|> castError(SignUpError.self)
|
||||
|
||||
let switchedAccounts = accountManager.transaction { transaction -> Void in
|
||||
switchToAuthorizedAccount(transaction: transaction, account: account)
|
||||
}
|
||||
|> introduceError(SignUpError.self)
|
||||
|> castError(SignUpError.self)
|
||||
|
||||
if let avatarData = avatarData {
|
||||
let resource = LocalFileMediaResource(fileId: arc4random64())
|
||||
|
@ -147,7 +147,7 @@ public final class BlockedPeersContext {
|
||||
return self.account.postbox.transaction { transaction -> Api.InputUser? in
|
||||
return transaction.getPeer(peerId).flatMap(apiInputUser)
|
||||
}
|
||||
|> introduceError(BlockedPeersContextAddError.self)
|
||||
|> castError(BlockedPeersContextAddError.self)
|
||||
|> mapToSignal { [weak self] inputUser -> Signal<Never, BlockedPeersContextAddError> in
|
||||
guard let inputUser = inputUser else {
|
||||
return .fail(.generic)
|
||||
@ -169,7 +169,7 @@ public final class BlockedPeersContext {
|
||||
})
|
||||
return transaction.getPeer(peerId)
|
||||
}
|
||||
|> introduceError(BlockedPeersContextAddError.self)
|
||||
|> castError(BlockedPeersContextAddError.self)
|
||||
}
|
||||
|> deliverOnMainQueue
|
||||
|
||||
@ -204,7 +204,7 @@ public final class BlockedPeersContext {
|
||||
return self.account.postbox.transaction { transaction -> Api.InputUser? in
|
||||
return transaction.getPeer(peerId).flatMap(apiInputUser)
|
||||
}
|
||||
|> introduceError(BlockedPeersContextRemoveError.self)
|
||||
|> castError(BlockedPeersContextRemoveError.self)
|
||||
|> mapToSignal { [weak self] inputUser -> Signal<Never, BlockedPeersContextRemoveError> in
|
||||
guard let inputUser = inputUser else {
|
||||
return .fail(.generic)
|
||||
@ -226,7 +226,7 @@ public final class BlockedPeersContext {
|
||||
})
|
||||
return transaction.getPeer(peerId)
|
||||
}
|
||||
|> introduceError(BlockedPeersContextRemoveError.self)
|
||||
|> castError(BlockedPeersContextRemoveError.self)
|
||||
}
|
||||
|> deliverOnMainQueue
|
||||
|> mapToSignal { _ -> Signal<Never, BlockedPeersContextRemoveError> in
|
||||
|
@ -115,7 +115,7 @@ public func channelAdminLogEvents(postbox: Postbox, network: Network, peerId: Pe
|
||||
return postbox.transaction { transaction -> (Peer?, [Peer]?) in
|
||||
return (transaction.getPeer(peerId), admins?.compactMap { transaction.getPeer($0) })
|
||||
}
|
||||
|> introduceError(ChannelAdminLogEventError.self)
|
||||
|> castError(ChannelAdminLogEventError.self)
|
||||
|> mapToSignal { (peer, admins) -> Signal<AdminLogEventsResult, ChannelAdminLogEventError> in
|
||||
if let peer = peer, let inputChannel = apiInputChannel(peer) {
|
||||
let inputAdmins = admins?.compactMap { apiInputUser($0) }
|
||||
@ -231,7 +231,7 @@ public func channelAdminLogEvents(postbox: Postbox, network: Network, peerId: Pe
|
||||
return postbox.transaction { transaction -> AdminLogEventsResult in
|
||||
updatePeers(transaction: transaction, peers: peers.map { $0.1 }, update: { return $1 })
|
||||
return AdminLogEventsResult(peerId: peerId, peers: peers, events: events)
|
||||
} |> introduceError(MTRpcError.self)
|
||||
} |> castError(MTRpcError.self)
|
||||
}
|
||||
|
||||
} |> mapError {_ in return .generic}
|
||||
|
@ -65,14 +65,14 @@ private func createChannel(account: Account, title: String, description: String?
|
||||
|> map { _ in
|
||||
return peerId
|
||||
}
|
||||
|> introduceError(CreateChannelError.self)
|
||||
|> castError(CreateChannelError.self)
|
||||
|> timeout(5.0, queue: Queue.concurrentDefaultQueue(), alternate: .fail(.generic))
|
||||
} else {
|
||||
return .fail(.generic)
|
||||
}
|
||||
}
|
||||
}
|
||||
|> introduceError(CreateChannelError.self)
|
||||
|> castError(CreateChannelError.self)
|
||||
|> switchToLatest
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,7 @@ public func updateChannelHistoryAvailabilitySettingsInteractively(postbox: Postb
|
||||
return postbox.transaction { transaction -> Peer? in
|
||||
return transaction.getPeer(peerId)
|
||||
}
|
||||
|> introduceError(ChannelHistoryAvailabilityError.self)
|
||||
|> castError(ChannelHistoryAvailabilityError.self)
|
||||
|> mapToSignal { peer in
|
||||
|
||||
guard let peer = peer, let inputChannel = apiInputChannel(peer) else {
|
||||
@ -47,7 +47,7 @@ public func updateChannelHistoryAvailabilitySettingsInteractively(postbox: Postb
|
||||
return currentData
|
||||
}
|
||||
})
|
||||
} |> introduceError(ChannelHistoryAvailabilityError.self)
|
||||
} |> castError(ChannelHistoryAvailabilityError.self)
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ public func checkOwnershipTranfserAvailability(postbox: Postbox, network: Networ
|
||||
return postbox.transaction { transaction -> Peer? in
|
||||
return transaction.getPeer(memberId)
|
||||
}
|
||||
|> introduceError(ChannelOwnershipTransferError.self)
|
||||
|> castError(ChannelOwnershipTransferError.self)
|
||||
|> mapToSignal { user -> Signal<Never, ChannelOwnershipTransferError> in
|
||||
guard let user = user else {
|
||||
return .fail(.generic)
|
||||
|
@ -17,7 +17,7 @@ public func channelStatsUrl(postbox: Postbox, network: Network, peerId: PeerId,
|
||||
return postbox.transaction { transaction -> Api.InputPeer? in
|
||||
return transaction.getPeer(peerId).flatMap(apiInputPeer)
|
||||
}
|
||||
|> introduceError(ChannelStatsUrlError.self)
|
||||
|> castError(ChannelStatsUrlError.self)
|
||||
|> mapToSignal { inputPeer -> Signal<String, ChannelStatsUrlError> in
|
||||
guard let inputPeer = inputPeer else {
|
||||
return .fail(.generic)
|
||||
|
@ -49,7 +49,7 @@ public func createGroup(account: Account, title: String, peerIds: [PeerId]) -> S
|
||||
return view.peers[peerId] != nil
|
||||
}
|
||||
|> take(1)
|
||||
|> introduceError(CreateGroupError.self)
|
||||
|> castError(CreateGroupError.self)
|
||||
|> map { _ in
|
||||
return peerId
|
||||
}
|
||||
@ -58,6 +58,6 @@ public func createGroup(account: Account, title: String, peerIds: [PeerId]) -> S
|
||||
}
|
||||
}
|
||||
}
|
||||
|> introduceError(CreateGroupError.self)
|
||||
|> castError(CreateGroupError.self)
|
||||
|> switchToLatest
|
||||
}
|
||||
|
@ -53,14 +53,14 @@ func fetchResource(account: Account, resource: MediaResource, intervals: Signal<
|
||||
|> then(fetchCloudMediaLocation(account: account, resource: cloudResource, datacenterId: cloudResource.datacenterId, size: resource.size == 0 ? nil : resource.size, intervals: intervals, parameters: parameters))
|
||||
} else if let webFileResource = resource as? WebFileReferenceMediaResource {
|
||||
return currentWebDocumentsHostDatacenterId(postbox: account.postbox, isTestingEnvironment: account.testingEnvironment)
|
||||
|> introduceError(MediaResourceDataFetchError.self)
|
||||
|> castError(MediaResourceDataFetchError.self)
|
||||
|> mapToSignal { datacenterId -> Signal<MediaResourceDataFetchResult, MediaResourceDataFetchError> in
|
||||
return .single(.dataPart(resourceOffset: 0, data: Data(), range: 0 ..< 0, complete: false))
|
||||
|> then(fetchCloudMediaLocation(account: account, resource: webFileResource, datacenterId: Int(datacenterId), size: resource.size == 0 ? nil : resource.size, intervals: intervals, parameters: parameters))
|
||||
}
|
||||
} else if let localFileResource = resource as? LocalFileReferenceMediaResource {
|
||||
return fetchLocalFileResource(path: localFileResource.localFilePath, move: localFileResource.isUniquelyReferencedTemporaryFile)
|
||||
|> introduceError(MediaResourceDataFetchError.self)
|
||||
|> castError(MediaResourceDataFetchError.self)
|
||||
} else if let httpReference = resource as? HttpReferenceMediaResource {
|
||||
return .single(.dataPart(resourceOffset: 0, data: Data(), range: 0 ..< 0, complete: false))
|
||||
|> then(fetchHttpResource(url: httpReference.url))
|
||||
|
@ -839,7 +839,7 @@ final class MediaReferenceRevalidationContext {
|
||||
return .complete()
|
||||
}
|
||||
|> then(loadRecentGifs)
|
||||
|> introduceError(RevalidateMediaReferenceError.self)).start(next: { value in
|
||||
|> castError(RevalidateMediaReferenceError.self)).start(next: { value in
|
||||
next(value)
|
||||
}, error: { _ in
|
||||
error(.generic)
|
||||
|
@ -54,7 +54,7 @@ public func addContactInteractively(account: Account, peerId: PeerId, firstName:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|> introduceError(AddContactError.self)
|
||||
|> castError(AddContactError.self)
|
||||
|> mapToSignal { inputUserAndPhone in
|
||||
guard let (inputUser, phone) = inputUserAndPhone else {
|
||||
return .fail(.generic)
|
||||
@ -93,7 +93,7 @@ public func addContactInteractively(account: Account, peerId: PeerId, firstName:
|
||||
|
||||
account.stateManager.addUpdates(result)
|
||||
}
|
||||
|> introduceError(AddContactError.self)
|
||||
|> castError(AddContactError.self)
|
||||
|> ignoreValues
|
||||
}
|
||||
}
|
||||
@ -107,7 +107,7 @@ public func acceptAndShareContact(account: Account, peerId: PeerId) -> Signal<Ne
|
||||
return account.postbox.transaction { transaction -> Api.InputUser? in
|
||||
return transaction.getPeer(peerId).flatMap(apiInputUser)
|
||||
}
|
||||
|> introduceError(AcceptAndShareContactError.self)
|
||||
|> castError(AcceptAndShareContactError.self)
|
||||
|> mapToSignal { inputUser -> Signal<Never, AcceptAndShareContactError> in
|
||||
guard let inputUser = inputUser else {
|
||||
return .fail(.generic)
|
||||
|
@ -17,7 +17,7 @@ public enum JoinChannelError {
|
||||
public func joinChannel(account: Account, peerId: PeerId) -> Signal<RenderedChannelParticipant?, JoinChannelError> {
|
||||
return account.postbox.loadedPeerWithId(peerId)
|
||||
|> take(1)
|
||||
|> introduceError(JoinChannelError.self)
|
||||
|> castError(JoinChannelError.self)
|
||||
|> mapToSignal { peer -> Signal<RenderedChannelParticipant?, JoinChannelError> in
|
||||
if let inputChannel = apiInputChannel(peer) {
|
||||
return account.network.request(Api.functions.channels.joinChannel(channel: inputChannel))
|
||||
@ -64,7 +64,7 @@ public func joinChannel(account: Account, peerId: PeerId) -> Signal<RenderedChan
|
||||
}
|
||||
return RenderedChannelParticipant(participant: updatedParticipant, peer: peer, peers: peers, presences: presences)
|
||||
}
|
||||
|> introduceError(JoinChannelError.self)
|
||||
|> castError(JoinChannelError.self)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -49,7 +49,7 @@ public func joinChatInteractively(with hash: String, account: Account) -> Signal
|
||||
account.stateManager.addUpdates(updates)
|
||||
if let peerId = apiUpdatesGroups(updates).first?.peerId {
|
||||
return account.postbox.multiplePeersView([peerId])
|
||||
|> introduceError(JoinLinkError.self)
|
||||
|> castError(JoinLinkError.self)
|
||||
|> filter { view in
|
||||
return view.peers[peerId] != nil
|
||||
}
|
||||
@ -57,7 +57,7 @@ public func joinChatInteractively(with hash: String, account: Account) -> Signal
|
||||
|> map { _ in
|
||||
return peerId
|
||||
}
|
||||
|> timeout(5.0, queue: Queue.concurrentDefaultQueue(), alternate: .single(nil) |> introduceError(JoinLinkError.self))
|
||||
|> timeout(5.0, queue: Queue.concurrentDefaultQueue(), alternate: .single(nil) |> castError(JoinLinkError.self))
|
||||
}
|
||||
return .single(nil)
|
||||
}
|
||||
|
@ -172,12 +172,12 @@ public func downloadAndApplyLocalization(accountManager: AccountManager, postbox
|
||||
|> mapToSignal { _ -> Signal<Void, NoError> in
|
||||
return .complete()
|
||||
}
|
||||
|> introduceError(DownloadAndApplyLocalizationError.self)
|
||||
|> castError(DownloadAndApplyLocalizationError.self)
|
||||
}
|
||||
|> introduceError(DownloadAndApplyLocalizationError.self)
|
||||
|> castError(DownloadAndApplyLocalizationError.self)
|
||||
|> switchToLatest
|
||||
}
|
||||
|> introduceError(DownloadAndApplyLocalizationError.self)
|
||||
|> castError(DownloadAndApplyLocalizationError.self)
|
||||
|> switchToLatest
|
||||
}
|
||||
}
|
||||
|
@ -12,17 +12,17 @@ public enum InternalUpdaterError {
|
||||
|
||||
public func requestUpdatesXml(account: Account, source: String) -> Signal<Data, InternalUpdaterError> {
|
||||
return resolvePeerByName(account: account, name: source)
|
||||
|> introduceError(InternalUpdaterError.self)
|
||||
|> castError(InternalUpdaterError.self)
|
||||
|> mapToSignal { peerId -> Signal<Peer?, InternalUpdaterError> in
|
||||
return account.postbox.transaction { transaction in
|
||||
return peerId != nil ? transaction.getPeer(peerId!) : nil
|
||||
} |> introduceError(InternalUpdaterError.self)
|
||||
} |> castError(InternalUpdaterError.self)
|
||||
}
|
||||
|> mapToSignal { peer in
|
||||
if let peer = peer, let inputPeer = apiInputPeer(peer) {
|
||||
return account.network.request(Api.functions.messages.getHistory(peer: inputPeer, offsetId: 0, offsetDate: 0, addOffset: 0, limit: 1, maxId: Int32.max, minId: 0, hash: 0))
|
||||
|> retryRequest
|
||||
|> introduceError(InternalUpdaterError.self)
|
||||
|> castError(InternalUpdaterError.self)
|
||||
|> mapToSignal { result in
|
||||
switch result {
|
||||
case let .channelMessages(_, _, _, apiMessages, apiChats, apiUsers):
|
||||
@ -79,17 +79,17 @@ public enum AppUpdateDownloadResult {
|
||||
|
||||
public func downloadAppUpdate(account: Account, source: String, fileName: String) -> Signal<AppUpdateDownloadResult, InternalUpdaterError> {
|
||||
return resolvePeerByName(account: account, name: source)
|
||||
|> introduceError(InternalUpdaterError.self)
|
||||
|> castError(InternalUpdaterError.self)
|
||||
|> mapToSignal { peerId -> Signal<Peer?, InternalUpdaterError> in
|
||||
return account.postbox.transaction { transaction in
|
||||
return peerId != nil ? transaction.getPeer(peerId!) : nil
|
||||
} |> introduceError(InternalUpdaterError.self)
|
||||
} |> castError(InternalUpdaterError.self)
|
||||
}
|
||||
|> mapToSignal { peer in
|
||||
if let peer = peer, let inputPeer = apiInputPeer(peer) {
|
||||
return account.network.request(Api.functions.messages.getHistory(peer: inputPeer, offsetId: 0, offsetDate: 0, addOffset: 0, limit: 10, maxId: Int32.max, minId: 0, hash: 0))
|
||||
|> retryRequest
|
||||
|> introduceError(InternalUpdaterError.self)
|
||||
|> castError(InternalUpdaterError.self)
|
||||
|> mapToSignal { result in
|
||||
switch result {
|
||||
case let .channelMessages(_, _, _, apiMessages, apiChats, apiUsers):
|
||||
|
@ -33,7 +33,7 @@ public func availableGroupsForChannelDiscussion(postbox: Postbox, network: Netwo
|
||||
updatePeers(transaction: transation, peers: peers, update: { _, updated in updated })
|
||||
return peers
|
||||
}
|
||||
|> introduceError(AvailableChannelDiscussionGroupError.self)
|
||||
|> castError(AvailableChannelDiscussionGroupError.self)
|
||||
}
|
||||
}
|
||||
|
||||
@ -104,7 +104,7 @@ public func updateGroupDiscussionForChannel(network: Network, postbox: Postbox,
|
||||
}
|
||||
}
|
||||
}
|
||||
|> introduceError(ChannelDiscussionGroupError.self)
|
||||
|> castError(ChannelDiscussionGroupError.self)
|
||||
|> map { _ in
|
||||
return result
|
||||
}
|
||||
|
@ -165,7 +165,7 @@ private func synchronizeLocalizationUpdates(accountManager: AccountManager, post
|
||||
}
|
||||
|
||||
let poll = currentLanguageAndVersion
|
||||
|> introduceError(SynchronizeLocalizationUpdatesError.self)
|
||||
|> castError(SynchronizeLocalizationUpdatesError.self)
|
||||
|> mapToSignal { (primary, secondary) -> Signal<Void, SynchronizeLocalizationUpdatesError> in
|
||||
var differences: [Signal<Api.LangPackDifference, MTRpcError>] = []
|
||||
differences.append(network.request(Api.functions.langpack.getDifference(langCode: primary.code, fromVersion: primary.version)))
|
||||
@ -242,7 +242,7 @@ private func synchronizeLocalizationUpdates(accountManager: AccountManager, post
|
||||
return Void()
|
||||
}
|
||||
}
|
||||
|> introduceError(Void.self)
|
||||
|> castError(Void.self)
|
||||
|> switchToLatest
|
||||
}
|
||||
}) |> restart) |> `catch` { _ -> Signal<Void, NoError> in
|
||||
|
@ -401,7 +401,7 @@ private func synchronizeInstalledStickerPacks(transaction: Transaction, postbox:
|
||||
)
|
||||
|> then(.fail(.done))
|
||||
}
|
||||
|> introduceError(SynchronizeInstalledStickerPacksError.self)
|
||||
|> castError(SynchronizeInstalledStickerPacksError.self)
|
||||
|> switchToLatest
|
||||
}
|
||||
}
|
||||
|
@ -97,7 +97,7 @@ private final class MessageReactionCategoryContext {
|
||||
let inputPeer = transaction.getPeer(messageId.peerId).flatMap(apiInputPeer)
|
||||
return inputPeer
|
||||
}
|
||||
|> introduceError(LoadReactionsError.self)
|
||||
|> castError(LoadReactionsError.self)
|
||||
|> mapToSignal { inputPeer -> Signal<Api.MessageReactionsList, LoadReactionsError> in
|
||||
guard let inputPeer = inputPeer else {
|
||||
return .fail(.generic)
|
||||
|
@ -78,7 +78,7 @@ private func requestUpdateMessageReaction(postbox: Postbox, network: Network, st
|
||||
}
|
||||
return (peer, value)
|
||||
}
|
||||
|> introduceError(RequestUpdateMessageReactionError.self)
|
||||
|> castError(RequestUpdateMessageReactionError.self)
|
||||
|> mapToSignal { peerAndValue in
|
||||
guard let (peer, value) = peerAndValue else {
|
||||
return .fail(.generic)
|
||||
@ -115,7 +115,7 @@ private func requestUpdateMessageReaction(postbox: Postbox, network: Network, st
|
||||
})
|
||||
stateManager.addUpdates(result)
|
||||
}
|
||||
|> introduceError(RequestUpdateMessageReactionError.self)
|
||||
|> castError(RequestUpdateMessageReactionError.self)
|
||||
|> ignoreValues
|
||||
}
|
||||
}*/
|
||||
|
@ -147,7 +147,7 @@ public func updatePeerPhotoInternal(postbox: Postbox, network: Network, stateMan
|
||||
}
|
||||
|
||||
return mapResourceToAvatarSizes(result.resource, groupOrChannel.profileImageRepresentations)
|
||||
|> introduceError(UploadPeerPhotoError.self)
|
||||
|> castError(UploadPeerPhotoError.self)
|
||||
|> mapToSignal { generatedData -> Signal<(UpdatePeerPhotoStatus, MediaResource?), UploadPeerPhotoError> in
|
||||
stateManager?.addUpdates(updates)
|
||||
|
||||
|
@ -38,7 +38,7 @@ public final class PeersNearbyContext {
|
||||
|> `catch` { _ -> Signal<Api.Updates?, NoError> in
|
||||
return .single(nil)
|
||||
}
|
||||
|> introduceError(Void.self)
|
||||
|> castError(Void.self)
|
||||
|> mapToSignal { updates -> Signal<[PeerNearby], Void> in
|
||||
var peersNearby: [PeerNearby] = []
|
||||
if let updates = updates {
|
||||
@ -59,7 +59,7 @@ public final class PeersNearbyContext {
|
||||
return .single(peersNearby)
|
||||
|> then(
|
||||
accountStateManager.updatedPeersNearby()
|
||||
|> introduceError(Void.self)
|
||||
|> castError(Void.self)
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,7 @@ public enum RequestMessageSelectPollOptionError {
|
||||
public func requestMessageSelectPollOption(account: Account, messageId: MessageId, opaqueIdentifier: Data?) -> Signal<Never, RequestMessageSelectPollOptionError> {
|
||||
return account.postbox.loadedPeerWithId(messageId.peerId)
|
||||
|> take(1)
|
||||
|> introduceError(RequestMessageSelectPollOptionError.self)
|
||||
|> castError(RequestMessageSelectPollOptionError.self)
|
||||
|> mapToSignal { peer in
|
||||
if let inputPeer = apiInputPeer(peer) {
|
||||
return account.network.request(Api.functions.messages.sendVote(peer: inputPeer, msgId: messageId.id, options: opaqueIdentifier.flatMap({ [Buffer(data: $0)] }) ?? []))
|
||||
|
@ -28,7 +28,7 @@ public func requestChatContextResults(account: Account, botId: PeerId, peerId: P
|
||||
return nil
|
||||
}
|
||||
}, location)
|
||||
|> introduceError(RequestChatContextResultsError.self)
|
||||
|> castError(RequestChatContextResultsError.self)
|
||||
|> mapToSignal { botAndPeer, location -> Signal<ChatContextResultCollection?, RequestChatContextResultsError> in
|
||||
if let (bot, peer) = botAndPeer, let inputBot = apiInputUser(bot) {
|
||||
var flags: Int32 = 0
|
||||
|
@ -113,7 +113,7 @@ public func resolvePeerByName(account: Account, name: String, ageLimit: Int32 =
|
||||
transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.resolvedByNamePeers, key: CachedResolvedByNamePeer.key(name: normalizedName)), entry: CachedResolvedByNamePeer(peerId: peerId, timestamp: timestamp), collectionSpec: resolvedByNamePeersCollectionSpec)
|
||||
return peerId
|
||||
}
|
||||
|> introduceError(Void.self)
|
||||
|> castError(Void.self)
|
||||
}
|
||||
|> `catch` { _ -> Signal<PeerId?, NoError> in
|
||||
return .single(nil)
|
||||
|
@ -161,7 +161,7 @@ private func sendScheduledMessageNow(postbox: Postbox, network: Network, stateMa
|
||||
}
|
||||
return peer
|
||||
}
|
||||
|> introduceError(SendScheduledMessageNowError.self)
|
||||
|> castError(SendScheduledMessageNowError.self)
|
||||
|> mapToSignal { peer -> Signal<Never, SendScheduledMessageNowError> in
|
||||
guard let peer = peer else {
|
||||
return .fail(.generic)
|
||||
|
@ -16,7 +16,7 @@ public func updateChannelSlowModeInteractively(postbox: Postbox, network: Networ
|
||||
return postbox.transaction { transaction -> Peer? in
|
||||
return transaction.getPeer(peerId)
|
||||
}
|
||||
|> introduceError(UpdateChannelSlowModeError.self)
|
||||
|> castError(UpdateChannelSlowModeError.self)
|
||||
|> mapToSignal { peer in
|
||||
guard let peer = peer, let inputChannel = apiInputChannel(peer) else {
|
||||
return .fail(.generic)
|
||||
@ -34,7 +34,7 @@ public func updateChannelSlowModeInteractively(postbox: Postbox, network: Networ
|
||||
return currentData.withUpdatedSlowModeTimeout(timeout)
|
||||
})
|
||||
}
|
||||
|> introduceError(UpdateChannelSlowModeError.self)
|
||||
|> castError(UpdateChannelSlowModeError.self)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -97,7 +97,7 @@ public func standaloneUploadedImage(account: Account, peerId: PeerId, text: Stri
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|> introduceError(StandaloneUploadMediaError.self)
|
||||
|> castError(StandaloneUploadMediaError.self)
|
||||
|> mapToSignal { inputChat -> Signal<StandaloneUploadMediaEvent, StandaloneUploadMediaError> in
|
||||
guard let inputChat = inputChat else {
|
||||
return .fail(.generic)
|
||||
@ -191,7 +191,7 @@ public func standaloneUploadedFile(account: Account, peerId: PeerId, text: Strin
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|> introduceError(StandaloneUploadMediaError.self)
|
||||
|> castError(StandaloneUploadMediaError.self)
|
||||
|> mapToSignal { inputChat -> Signal<StandaloneUploadMediaEvent, StandaloneUploadMediaError> in
|
||||
guard let inputChat = inputChat else {
|
||||
return .fail(.generic)
|
||||
|
@ -330,7 +330,7 @@ public func createTheme(account: Account, title: String, resource: MediaResource
|
||||
transaction.replaceOrderedItemListItems(collectionId: Namespaces.OrderedItemList.CloudThemes, items: updatedEntries)
|
||||
return .result(theme)
|
||||
}
|
||||
|> introduceError(CreateThemeError.self)
|
||||
|> castError(CreateThemeError.self)
|
||||
} else {
|
||||
return .fail(.generic)
|
||||
}
|
||||
@ -426,7 +426,7 @@ public func updateTheme(account: Account, accountManager: AccountManager, theme:
|
||||
transaction.replaceOrderedItemListItems(collectionId: Namespaces.OrderedItemList.CloudThemes, items: updatedEntries)
|
||||
return .result(updatedTheme)
|
||||
}
|
||||
|> introduceError(CreateThemeError.self)
|
||||
|> castError(CreateThemeError.self)
|
||||
} else {
|
||||
return .fail(.generic)
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ public enum UpdateGroupSpecificStickersetError {
|
||||
|
||||
public func updateGroupSpecificStickerset(postbox: Postbox, network: Network, peerId: PeerId, info: StickerPackCollectionInfo?) -> Signal<Void, UpdateGroupSpecificStickersetError> {
|
||||
return postbox.loadedPeerWithId(peerId)
|
||||
|> introduceError(UpdateGroupSpecificStickersetError.self)
|
||||
|> castError(UpdateGroupSpecificStickersetError.self)
|
||||
|> mapToSignal { peer -> Signal<Void, UpdateGroupSpecificStickersetError> in
|
||||
let inputStickerset: Api.InputStickerSet
|
||||
if let info = info {
|
||||
@ -36,7 +36,7 @@ public func updateGroupSpecificStickerset(postbox: Postbox, network: Network, pe
|
||||
return (current as? CachedChannelData)?.withUpdatedStickerPack(info)
|
||||
})
|
||||
}
|
||||
|> introduceError(UpdateGroupSpecificStickersetError.self)
|
||||
|> castError(UpdateGroupSpecificStickersetError.self)
|
||||
default:
|
||||
return .complete()
|
||||
}
|
||||
|
@ -130,7 +130,7 @@ public final class TonInstance {
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate func importWallet(keychain: TonKeychain, wordList: [String], serverSalt: Data) -> Signal<WalletInfo, ImportWalletError> {
|
||||
fileprivate func importWallet(keychain: TonKeychain, wordList: [String], serverSalt: Data) -> Signal<WalletInfo, ImportWalletInternalError> {
|
||||
return Signal { subscriber in
|
||||
let disposable = MetaDisposable()
|
||||
|
||||
@ -139,13 +139,11 @@ public final class TonInstance {
|
||||
let cancel = ton.importKey(withLocalPassword: serverSalt, mnemonicPassword: Data(), wordList: wordList).start(next: { key in
|
||||
guard let key = key as? TONKey else {
|
||||
subscriber.putError(.generic)
|
||||
subscriber.putCompletion()
|
||||
return
|
||||
}
|
||||
let cancel = keychain.encrypt(key.secret).start(next: { encryptedSecretData in
|
||||
guard let encryptedSecretData = encryptedSecretData else {
|
||||
subscriber.putError(.generic)
|
||||
subscriber.putCompletion()
|
||||
return
|
||||
}
|
||||
subscriber.putNext(WalletInfo(publicKey: WalletPublicKey(rawValue: key.publicKey), encryptedSecret: EncryptedWalletSecret(rawValue: encryptedSecretData)))
|
||||
@ -153,7 +151,21 @@ public final class TonInstance {
|
||||
}, error: { _ in
|
||||
}, completed: {
|
||||
})
|
||||
}, error: { _ in
|
||||
}, error: { error in
|
||||
if let error = error as? TONError {
|
||||
#warning("Use error kind APIs")
|
||||
let filePrefix = "File \""
|
||||
let fileSuffix = "\" can't be created for writing"
|
||||
let text = error.text
|
||||
if text.hasPrefix(filePrefix) && text.hasSuffix(fileSuffix) {
|
||||
let filePath = String(error.text[text.index(text.startIndex, offsetBy: filePrefix.count) ..< text.index(text.endIndex, offsetBy: -fileSuffix.count)])
|
||||
subscriber.putError(.fileExists(filePath))
|
||||
} else {
|
||||
subscriber.putError(.generic)
|
||||
}
|
||||
} else {
|
||||
subscriber.putError(.generic)
|
||||
}
|
||||
}, completed: {
|
||||
})
|
||||
disposable.set(ActionDisposable {
|
||||
@ -216,7 +228,7 @@ public final class TonInstance {
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate func getWalletState(address: String) -> Signal<WalletState, NoError> {
|
||||
private func getWalletStateRaw(address: String) -> Signal<TONAccountState, NoError> {
|
||||
return Signal { subscriber in
|
||||
let disposable = MetaDisposable()
|
||||
|
||||
@ -226,7 +238,7 @@ public final class TonInstance {
|
||||
guard let state = state as? TONAccountState else {
|
||||
return
|
||||
}
|
||||
subscriber.putNext(WalletState(balance: state.balance, lastTransactionId: state.lastTransactionId.flatMap(WalletTransactionId.init(tonTransactionId:))))
|
||||
subscriber.putNext(state)
|
||||
}, error: { _ in
|
||||
}, completed: {
|
||||
subscriber.putCompletion()
|
||||
@ -241,6 +253,13 @@ public final class TonInstance {
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate func getWalletState(address: String) -> Signal<WalletState, NoError> {
|
||||
return self.getWalletStateRaw(address: address)
|
||||
|> map { state in
|
||||
return WalletState(balance: state.balance, lastTransactionId: state.lastTransactionId.flatMap(WalletTransactionId.init(tonTransactionId:)))
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate func walletLastTransactionId(address: String) -> Signal<WalletTransactionId?, NoError> {
|
||||
return Signal { subscriber in
|
||||
let disposable = MetaDisposable()
|
||||
@ -316,7 +335,7 @@ public final class TonInstance {
|
||||
|
||||
fileprivate func getGramsFromTestGiver(address: String, amount: Int64) -> Signal<Void, GetGramsFromTestGiverError> {
|
||||
return self.getTestGiverAccountState()
|
||||
|> introduceError(GetGramsFromTestGiverError.self)
|
||||
|> castError(GetGramsFromTestGiverError.self)
|
||||
|> mapToSignal { state in
|
||||
guard let state = state else {
|
||||
return .fail(.generic)
|
||||
@ -343,39 +362,108 @@ public final class TonInstance {
|
||||
}
|
||||
}
|
||||
|
||||
private enum MakeWalletInitializedError {
|
||||
case generic
|
||||
}
|
||||
|
||||
private func makeWalletInitialized(key: TONKey, serverSalt: Data) -> Signal<Never, MakeWalletInitializedError> {
|
||||
return Signal { subscriber in
|
||||
let disposable = MetaDisposable()
|
||||
|
||||
self.impl.with { impl in
|
||||
impl.withInstance { ton in
|
||||
let cancel = ton.makeWalletInitialized(key, localPassword: serverSalt).start(next: { _ in
|
||||
preconditionFailure()
|
||||
}, error: { _ in
|
||||
subscriber.putError(.generic)
|
||||
}, completed: {
|
||||
subscriber.putCompletion()
|
||||
})
|
||||
disposable.set(ActionDisposable {
|
||||
cancel?.dispose()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return disposable
|
||||
}
|
||||
}
|
||||
|
||||
private func ensureWalletInitialized(address: String, key: TONKey, serverSalt: Data) -> Signal<Never, MakeWalletInitializedError> {
|
||||
return self.getWalletStateRaw(address: address)
|
||||
|> castError(MakeWalletInitializedError.self)
|
||||
|> mapToSignal { state -> Signal<Never, MakeWalletInitializedError> in
|
||||
if state.isInitialized {
|
||||
return .complete()
|
||||
} else {
|
||||
let poll: Signal<Void, MakeWalletInitializedError> = self.getWalletStateRaw(address: address)
|
||||
|> castError(MakeWalletInitializedError.self)
|
||||
|> mapToSignal { state -> Signal<Void, MakeWalletInitializedError> in
|
||||
if state.isInitialized {
|
||||
return .single(Void())
|
||||
} else {
|
||||
return .complete()
|
||||
}
|
||||
}
|
||||
|
||||
let pollUntilInitialized = (
|
||||
poll
|
||||
|> then(.complete()
|
||||
|> delay(2.0, queue: Queue.concurrentDefaultQueue()))
|
||||
)
|
||||
|> restart
|
||||
|> take(1)
|
||||
|
||||
return self.makeWalletInitialized(key: key, serverSalt: serverSalt)
|
||||
|> then(
|
||||
pollUntilInitialized
|
||||
|> ignoreValues
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate func sendGramsFromWallet(keychain: TonKeychain, serverSalt: Data, walletInfo: WalletInfo, fromAddress: String, toAddress: String, amount: Int64, textMessage: String) -> Signal<Never, SendGramsFromWalletError> {
|
||||
return keychain.decrypt(walletInfo.encryptedSecret.rawValue)
|
||||
|> introduceError(SendGramsFromWalletError.self)
|
||||
|> castError(SendGramsFromWalletError.self)
|
||||
|> mapToSignal { decryptedSecret -> Signal<Never, SendGramsFromWalletError> in
|
||||
guard let decryptedSecret = decryptedSecret else {
|
||||
return .fail(.secretDecryptionFailed)
|
||||
}
|
||||
return Signal { subscriber in
|
||||
let disposable = MetaDisposable()
|
||||
|
||||
self.impl.with { impl in
|
||||
impl.withInstance { ton in
|
||||
let cancel = ton.sendGrams(from: TONKey(publicKey: walletInfo.publicKey.rawValue, secret: decryptedSecret), localPassword: serverSalt, fromAddress: fromAddress, toAddress: toAddress, amount: amount, textMessage: textMessage).start(next: { _ in
|
||||
preconditionFailure()
|
||||
}, error: { _ in
|
||||
subscriber.putError(.generic)
|
||||
}, completed: {
|
||||
subscriber.putCompletion()
|
||||
})
|
||||
disposable.set(ActionDisposable {
|
||||
cancel?.dispose()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return disposable
|
||||
let key = TONKey(publicKey: walletInfo.publicKey.rawValue, secret: decryptedSecret)
|
||||
|
||||
return self.ensureWalletInitialized(address: fromAddress, key: key, serverSalt: serverSalt)
|
||||
|> mapError { _ -> SendGramsFromWalletError in
|
||||
return .generic
|
||||
}
|
||||
|> then(
|
||||
Signal<Never, SendGramsFromWalletError> { subscriber in
|
||||
let disposable = MetaDisposable()
|
||||
|
||||
self.impl.with { impl in
|
||||
impl.withInstance { ton in
|
||||
let cancel = ton.sendGrams(from: key, localPassword: serverSalt, fromAddress: fromAddress, toAddress: toAddress, amount: amount, textMessage: textMessage).start(next: { _ in
|
||||
preconditionFailure()
|
||||
}, error: { _ in
|
||||
subscriber.putError(.generic)
|
||||
}, completed: {
|
||||
subscriber.putCompletion()
|
||||
})
|
||||
disposable.set(ActionDisposable {
|
||||
cancel?.dispose()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return disposable
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate func walletRestoreWords(walletInfo: WalletInfo, keychain: TonKeychain, serverSalt: Data) -> Signal<[String], WalletRestoreWordsError> {
|
||||
return keychain.decrypt(walletInfo.encryptedSecret.rawValue)
|
||||
|> introduceError(WalletRestoreWordsError.self)
|
||||
|> castError(WalletRestoreWordsError.self)
|
||||
|> mapToSignal { decryptedSecret -> Signal<[String], WalletRestoreWordsError> in
|
||||
guard let decryptedSecret = decryptedSecret else {
|
||||
return .fail(.secretDecryptionFailed)
|
||||
@ -408,7 +496,7 @@ public final class TonInstance {
|
||||
}
|
||||
}
|
||||
|
||||
public struct WalletPublicKey: Hashable {
|
||||
public struct WalletPublicKey: Codable, Hashable {
|
||||
public var rawValue: String
|
||||
|
||||
public init(rawValue: String) {
|
||||
@ -416,7 +504,7 @@ public struct WalletPublicKey: Hashable {
|
||||
}
|
||||
}
|
||||
|
||||
public struct EncryptedWalletSecret: Hashable {
|
||||
public struct EncryptedWalletSecret: Codable, Equatable {
|
||||
public var rawValue: Data
|
||||
|
||||
public init(rawValue: Data) {
|
||||
@ -424,7 +512,7 @@ public struct EncryptedWalletSecret: Hashable {
|
||||
}
|
||||
}
|
||||
|
||||
public struct WalletInfo: PostboxCoding, Equatable {
|
||||
public struct WalletInfo: PostboxCoding, Codable, Equatable {
|
||||
public let publicKey: WalletPublicKey
|
||||
public let encryptedSecret: EncryptedWalletSecret
|
||||
|
||||
@ -444,15 +532,57 @@ public struct WalletInfo: PostboxCoding, Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
public struct WalletCollection: PreferencesEntry {
|
||||
public var wallets: [WalletInfo]
|
||||
public struct CombinedWalletState: Codable, Equatable {
|
||||
public var walletState: WalletState
|
||||
public var timestamp: Int64
|
||||
public var topTransactions: [WalletTransaction]
|
||||
}
|
||||
|
||||
public struct WalletStateRecord: PostboxCoding, Equatable {
|
||||
public let info: WalletInfo
|
||||
public var state: CombinedWalletState?
|
||||
|
||||
public init(wallets: [WalletInfo]) {
|
||||
public init(info: WalletInfo, state: CombinedWalletState?) {
|
||||
self.info = info
|
||||
self.state = state
|
||||
}
|
||||
|
||||
public init(decoder: PostboxDecoder) {
|
||||
self.info = decoder.decodeDataForKey("info").flatMap { data in
|
||||
return try? JSONDecoder().decode(WalletInfo.self, from: data)
|
||||
} ?? WalletInfo(publicKey: WalletPublicKey(rawValue: ""), encryptedSecret: EncryptedWalletSecret(rawValue: Data()))
|
||||
self.state = decoder.decodeDataForKey("state").flatMap { data in
|
||||
return try? JSONDecoder().decode(CombinedWalletState.self, from: data)
|
||||
}
|
||||
}
|
||||
|
||||
public func encode(_ encoder: PostboxEncoder) {
|
||||
if let data = try? JSONEncoder().encode(self.info) {
|
||||
encoder.encodeData(data, forKey: "info")
|
||||
}
|
||||
if let state = self.state, let data = try? JSONEncoder().encode(state) {
|
||||
encoder.encodeData(data, forKey: "state")
|
||||
} else {
|
||||
encoder.encodeNil(forKey: "state")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public struct WalletCollection: PreferencesEntry {
|
||||
public var wallets: [WalletStateRecord]
|
||||
|
||||
public init(wallets: [WalletStateRecord]) {
|
||||
self.wallets = wallets
|
||||
}
|
||||
|
||||
public init(decoder: PostboxDecoder) {
|
||||
self.wallets = decoder.decodeObjectArrayWithDecoderForKey("wallets")
|
||||
var wallets: [WalletStateRecord] = decoder.decodeObjectArrayWithDecoderForKey("wallets")
|
||||
for i in (0 ..< wallets.count).reversed() {
|
||||
if wallets[i].info.publicKey.rawValue.isEmpty {
|
||||
wallets.remove(at: i)
|
||||
}
|
||||
}
|
||||
self.wallets = wallets
|
||||
}
|
||||
|
||||
public func encode(_ encoder: PostboxEncoder) {
|
||||
@ -487,21 +617,26 @@ public func createWallet(postbox: Postbox, network: Network, tonInstance: TonIns
|
||||
}
|
||||
|> mapToSignal { serverSalt -> Signal<(WalletInfo, [String]), CreateWalletError> in
|
||||
return tonInstance.createWallet(keychain: keychain, serverSalt: serverSalt)
|
||||
|> introduceError(CreateWalletError.self)
|
||||
|> castError(CreateWalletError.self)
|
||||
|> mapToSignal { walletInfo, wordList -> Signal<(WalletInfo, [String]), CreateWalletError> in
|
||||
return postbox.transaction { transaction -> (WalletInfo, [String]) in
|
||||
transaction.updatePreferencesEntry(key: PreferencesKeys.walletCollection, { current in
|
||||
var walletCollection = (current as? WalletCollection) ?? WalletCollection(wallets: [])
|
||||
walletCollection.wallets = [walletInfo]
|
||||
walletCollection.wallets = [WalletStateRecord(info: walletInfo, state: nil)]
|
||||
return walletCollection
|
||||
})
|
||||
return (walletInfo, wordList)
|
||||
}
|
||||
|> introduceError(CreateWalletError.self)
|
||||
|> castError(CreateWalletError.self)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private enum ImportWalletInternalError {
|
||||
case generic
|
||||
case fileExists(String)
|
||||
}
|
||||
|
||||
public enum ImportWalletError {
|
||||
case generic
|
||||
}
|
||||
@ -513,16 +648,28 @@ public func importWallet(postbox: Postbox, network: Network, tonInstance: TonIns
|
||||
}
|
||||
|> mapToSignal { serverSalt in
|
||||
return tonInstance.importWallet(keychain: keychain, wordList: wordList, serverSalt: serverSalt)
|
||||
|> `catch` { error -> Signal<WalletInfo, ImportWalletError> in
|
||||
switch error {
|
||||
case .generic:
|
||||
return .fail(.generic)
|
||||
case let .fileExists(path):
|
||||
let _ = try? FileManager.default.removeItem(atPath: path)
|
||||
return tonInstance.importWallet(keychain: keychain, wordList: wordList, serverSalt: serverSalt)
|
||||
|> mapError { _ -> ImportWalletError in
|
||||
return .generic
|
||||
}
|
||||
}
|
||||
}
|
||||
|> mapToSignal { walletInfo -> Signal<WalletInfo, ImportWalletError> in
|
||||
return postbox.transaction { transaction -> WalletInfo in
|
||||
transaction.updatePreferencesEntry(key: PreferencesKeys.walletCollection, { current in
|
||||
var walletCollection = (current as? WalletCollection) ?? WalletCollection(wallets: [])
|
||||
walletCollection.wallets = [walletInfo]
|
||||
walletCollection.wallets = [WalletStateRecord(info: walletInfo, state: nil)]
|
||||
return walletCollection
|
||||
})
|
||||
return walletInfo
|
||||
}
|
||||
|> introduceError(ImportWalletError.self)
|
||||
|> castError(ImportWalletError.self)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -553,7 +700,7 @@ public func walletRestoreWords(network: Network, walletInfo: WalletInfo, tonInst
|
||||
}
|
||||
}
|
||||
|
||||
public struct WalletState: Equatable {
|
||||
public struct WalletState: Codable, Equatable {
|
||||
public let balance: Int64
|
||||
public let lastTransactionId: WalletTransactionId?
|
||||
|
||||
@ -575,6 +722,67 @@ public func getWalletState(address: String, tonInstance: TonInstance) -> Signal<
|
||||
return tonInstance.getWalletState(address: address)
|
||||
}
|
||||
|
||||
public enum GetCombinedWalletStateError {
|
||||
case generic
|
||||
}
|
||||
|
||||
public enum CombinedWalletStateResult {
|
||||
case cached(CombinedWalletState?)
|
||||
case updated(CombinedWalletState)
|
||||
}
|
||||
|
||||
public func getCombinedWalletState(postbox: Postbox, walletInfo: WalletInfo, tonInstance: TonInstance) -> Signal<CombinedWalletStateResult, GetCombinedWalletStateError> {
|
||||
return postbox.transaction { transaction -> CombinedWalletState? in
|
||||
let walletCollection = (transaction.getPreferencesEntry(key: PreferencesKeys.walletCollection) as? WalletCollection) ?? WalletCollection(wallets: [])
|
||||
for item in walletCollection.wallets {
|
||||
if item.info.publicKey == walletInfo.publicKey {
|
||||
return item.state
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|> castError(GetCombinedWalletStateError.self)
|
||||
|> mapToSignal { cachedState -> Signal<CombinedWalletStateResult, GetCombinedWalletStateError> in
|
||||
return .single(.cached(cachedState))
|
||||
|> then(
|
||||
tonInstance.walletAddress(publicKey: walletInfo.publicKey)
|
||||
|> castError(GetCombinedWalletStateError.self)
|
||||
|> mapToSignal { address -> Signal<CombinedWalletStateResult, GetCombinedWalletStateError> in
|
||||
return getWalletState(address: address, tonInstance: tonInstance)
|
||||
|> castError(GetCombinedWalletStateError.self)
|
||||
|> mapToSignal { walletState -> Signal<CombinedWalletStateResult, GetCombinedWalletStateError> in
|
||||
let topTransactions: Signal<[WalletTransaction], GetCombinedWalletStateError>
|
||||
if walletState.lastTransactionId == cachedState?.walletState.lastTransactionId {
|
||||
topTransactions = .single(cachedState?.topTransactions ?? [])
|
||||
} else {
|
||||
topTransactions = getWalletTransactions(address: address, previousId: nil, tonInstance: tonInstance)
|
||||
|> mapError { _ -> GetCombinedWalletStateError in
|
||||
return .generic
|
||||
}
|
||||
}
|
||||
return topTransactions
|
||||
|> mapToSignal { topTransactions -> Signal<CombinedWalletStateResult, GetCombinedWalletStateError> in
|
||||
let combinedState = CombinedWalletState(walletState: walletState, timestamp: 0, topTransactions: topTransactions)
|
||||
return postbox.transaction { transaction -> CombinedWalletStateResult in
|
||||
transaction.updatePreferencesEntry(key: PreferencesKeys.walletCollection, { current in
|
||||
var walletCollection = (current as? WalletCollection) ?? WalletCollection(wallets: [])
|
||||
for i in 0 ..< walletCollection.wallets.count {
|
||||
if walletCollection.wallets[i].info.publicKey == walletInfo.publicKey {
|
||||
walletCollection.wallets[i].state = combinedState
|
||||
}
|
||||
}
|
||||
return walletCollection
|
||||
})
|
||||
return .updated(combinedState)
|
||||
}
|
||||
|> castError(GetCombinedWalletStateError.self)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
public enum GetGramsFromTestGiverError {
|
||||
case generic
|
||||
}
|
||||
@ -595,14 +803,14 @@ public func sendGramsFromWallet(network: Network, tonInstance: TonInstance, keyc
|
||||
}
|
||||
|> mapToSignal { serverSalt in
|
||||
return walletAddress(publicKey: walletInfo.publicKey, tonInstance: tonInstance)
|
||||
|> introduceError(SendGramsFromWalletError.self)
|
||||
|> castError(SendGramsFromWalletError.self)
|
||||
|> mapToSignal { fromAddress in
|
||||
return tonInstance.sendGramsFromWallet(keychain: keychain, serverSalt: serverSalt, walletInfo: walletInfo, fromAddress: fromAddress, toAddress: toAddress, amount: amount, textMessage: textMessage)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public struct WalletTransactionId: Hashable {
|
||||
public struct WalletTransactionId: Codable, Hashable {
|
||||
public var lt: Int64
|
||||
public var transactionHash: Data
|
||||
}
|
||||
@ -614,7 +822,7 @@ private extension WalletTransactionId {
|
||||
}
|
||||
}
|
||||
|
||||
public final class WalletTransactionMessage: Equatable {
|
||||
public final class WalletTransactionMessage: Codable, Equatable {
|
||||
public let value: Int64
|
||||
public let source: String
|
||||
public let destination: String
|
||||
@ -650,7 +858,7 @@ private extension WalletTransactionMessage {
|
||||
}
|
||||
}
|
||||
|
||||
public final class WalletTransaction: Equatable {
|
||||
public final class WalletTransaction: Codable, Equatable {
|
||||
public let data: Data
|
||||
public let transactionId: WalletTransactionId
|
||||
public let timestamp: Int64
|
||||
@ -713,12 +921,33 @@ public enum GetWalletTransactionsError {
|
||||
}
|
||||
|
||||
public func getWalletTransactions(address: String, previousId: WalletTransactionId?, tonInstance: TonInstance) -> Signal<[WalletTransaction], GetWalletTransactionsError> {
|
||||
return getWalletTransactionsOnce(address: address, previousId: previousId, tonInstance: tonInstance)
|
||||
|> mapToSignal { transactions in
|
||||
guard let lastTransaction = transactions.last, transactions.count >= 2 else {
|
||||
return .single(transactions)
|
||||
}
|
||||
return getWalletTransactionsOnce(address: address, previousId: lastTransaction.transactionId, tonInstance: tonInstance)
|
||||
|> map { additionalTransactions in
|
||||
var result = transactions
|
||||
var existingIds = Set(result.map { $0.transactionId })
|
||||
for transaction in additionalTransactions {
|
||||
if !existingIds.contains(transaction.transactionId) {
|
||||
existingIds.insert(transaction.transactionId)
|
||||
result.append(transaction)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func getWalletTransactionsOnce(address: String, previousId: WalletTransactionId?, tonInstance: TonInstance) -> Signal<[WalletTransaction], GetWalletTransactionsError> {
|
||||
let previousIdValue: Signal<WalletTransactionId?, GetWalletTransactionsError>
|
||||
if let previousId = previousId {
|
||||
previousIdValue = .single(previousId)
|
||||
} else {
|
||||
previousIdValue = tonInstance.walletLastTransactionId(address: address)
|
||||
|> introduceError(GetWalletTransactionsError.self)
|
||||
|> castError(GetWalletTransactionsError.self)
|
||||
}
|
||||
return previousIdValue
|
||||
|> mapToSignal { previousId in
|
||||
|
Loading…
x
Reference in New Issue
Block a user