diff --git a/BlockchainSdk/Blockchains/Tron/TronWalletManager.swift b/BlockchainSdk/Blockchains/Tron/TronWalletManager.swift index b0797532b..db68898fd 100644 --- a/BlockchainSdk/Blockchains/Tron/TronWalletManager.swift +++ b/BlockchainSdk/Blockchains/Tron/TronWalletManager.swift @@ -262,38 +262,72 @@ extension TronWalletManager: TronTransactionDataBuilder { // MARK: - StakeKitTransactionSender extension TronWalletManager: StakeKitTransactionSender { - func sendStakeKit(transaction: StakeKitTransaction, signer: any TransactionSigner) -> AnyPublisher { - 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 { + return .anyFail(error: .init(error: BlockchainSdkError.notImplemented)) } } diff --git a/BlockchainSdk/Common/Interfaces/WalletManager.swift b/BlockchainSdk/Common/Interfaces/WalletManager.swift index 86fff4c5e..689032aea 100644 --- a/BlockchainSdk/Common/Interfaces/WalletManager.swift +++ b/BlockchainSdk/Common/Interfaces/WalletManager.swift @@ -75,6 +75,13 @@ public protocol TransactionSender { public protocol StakeKitTransactionSender { func sendStakeKit(transaction: StakeKitTransaction, signer: TransactionSigner) -> AnyPublisher + 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 {