Skip to content

Commit

Permalink
IOS-7733 Tron multiple signing (#812)
Browse files Browse the repository at this point in the history
  • Loading branch information
tureck1y authored Aug 27, 2024
1 parent e5053b8 commit 979e383
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 30 deletions.
94 changes: 64 additions & 30 deletions BlockchainSdk/Blockchains/Tron/TronWalletManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -262,38 +262,72 @@ extension TronWalletManager: TronTransactionDataBuilder {
// MARK: - StakeKitTransactionSender

extension TronWalletManager: StakeKitTransactionSender {
func sendStakeKit(transaction: StakeKitTransaction, signer: any TransactionSigner) -> AnyPublisher<TransactionSendResult, SendTxError> {
Result {
try TronStakeKitTransactionHelper().prepareForSign(transaction.unsignedData)
}
.publisher
.withWeakCaptureOf(self)
.flatMap { manager, input in
signer
.sign(hash: input.hash, walletPublicKey: manager.wallet.publicKey)
.tryMap { signature in
try manager.txBuilder.buildForSend(rawData: input.rawData, signature: signature)
func sendStakeKit(transactions: [StakeKitTransaction], signer: TransactionSigner) -> AnyPublisher<[TransactionSendResult], SendTxError> {

let presignedInputsPublisher = Result {
try transactions.map {
try TronStakeKitTransactionHelper().prepareForSign($0.unsignedData)
}
}.publisher

let readyToSendTransactionsPublisher = presignedInputsPublisher
.withWeakCaptureOf(self)
.flatMap { manager, inputs -> AnyPublisher<[Data], Error> in
signer
.sign(hashes: inputs.map { $0.hash }, walletPublicKey: manager.wallet.publicKey)
.tryMap { signatures -> [Data] in
try zip(inputs, signatures).map { (input, signature) in
try manager.txBuilder.buildForSend(rawData: input.rawData, signature: signature)
}
}
.eraseToAnyPublisher()
}

let sentTransactionsPublisher = readyToSendTransactionsPublisher
.flatMap { [weak self] transactionsData -> AnyPublisher<[TronBroadcastResponse], Error> in
guard let self else {
return .anyFail(error: WalletError.empty)
}
}
.withWeakCaptureOf(self)
.flatMap { manager, data in
manager.networkService
.broadcastHex(data)
.mapSendError(tx: data.hexString)
}
.withWeakCaptureOf(self)
.tryMap { manager, broadcastResponse in
guard broadcastResponse.result == true else {
throw WalletError.failedToSendTx

let sendPublishers = transactionsData
.map { data in
self.networkService
.broadcastHex(data)
.mapSendError(tx: data.hexString)
.eraseToAnyPublisher()
}

return Publishers.Sequence(sequence: sendPublishers)
.flatMap(maxPublishers: .max(1)) { $0 }
.collect()
.eraseToAnyPublisher()
}

let hash = broadcastResponse.txid
let mapper = PendingTransactionRecordMapper()
let record = mapper.mapToPendingTransactionRecord(stakeKitTransaction: transaction, hash: hash)
manager.wallet.addPendingTransaction(record)
return TransactionSendResult(hash: hash)
}
.eraseSendError()
.eraseToAnyPublisher()
return sentTransactionsPublisher
.withWeakCaptureOf(self)
.tryMap { manager, broadcastResponses -> [TransactionSendResult] in
guard broadcastResponses.count == transactions.count,
broadcastResponses.allSatisfy({ $0.result }) else {
throw WalletError.failedToSendTx
}

var results: [TransactionSendResult] = []

for (transaction, broadcastResponse) in zip(transactions, broadcastResponses) {
let hash = broadcastResponse.txid
let mapper = PendingTransactionRecordMapper()
let record = mapper.mapToPendingTransactionRecord(stakeKitTransaction: transaction, hash: hash)
manager.wallet.addPendingTransaction(record)
results.append(TransactionSendResult(hash: hash))
}

return results
}
.eraseSendError()
.eraseToAnyPublisher()
}

func sendStakeKit(transaction: StakeKitTransaction, signer: any TransactionSigner) -> AnyPublisher<TransactionSendResult, SendTxError> {
return .anyFail(error: .init(error: BlockchainSdkError.notImplemented))
}
}
7 changes: 7 additions & 0 deletions BlockchainSdk/Common/Interfaces/WalletManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,13 @@ public protocol TransactionSender {

public protocol StakeKitTransactionSender {
func sendStakeKit(transaction: StakeKitTransaction, signer: TransactionSigner) -> AnyPublisher<TransactionSendResult, SendTxError>
func sendStakeKit(transactions: [StakeKitTransaction], signer: TransactionSigner) -> AnyPublisher<[TransactionSendResult], SendTxError>
}

extension StakeKitTransactionSender {
func sendStakeKit(transactions: [StakeKitTransaction], signer: TransactionSigner) -> AnyPublisher<[TransactionSendResult], SendTxError> {
return .anyFail(error: .init(error: BlockchainSdkError.notImplemented))
}
}

public protocol TransactionSigner {
Expand Down

0 comments on commit 979e383

Please sign in to comment.