spb/os-vault Public
Self-custody, multi-chain crypto wallet for macOS. One recovery phrase, six chain families, zero API keys — nothing leaves your Mac.
Swift 96%
Shell 3.4%
Makefile 0.6%
1import Foundation2import Task_retrying34/// BlockchainClient that prepares and serialises transaction to send to blockchain5public protocol SolanaBlockchainClient: AnyObject {6 /// APIClient for handling network requests7 var apiClient: SolanaAPIClient { get set }89 /// Prepare a transaction base on its instructions10 /// - Parameters:11 /// - instructions: instructions of the transaction12 /// - signers: the signers13 /// - feePayer: the feePayer, usually is the first signer14 /// - recentBlockhash: recentBlockhash, can be fetched lately when the value is nil15 /// - feeCalculator: the fee calculator, leave it nil to use DefaultFeeCalculator16 /// - Returns: information of a prepared transaction17 func prepareTransaction(18 instructions: [TransactionInstruction],19 signers: [KeyPair],20 feePayer: PublicKey,21 feeCalculator: FeeCalculator?22 ) async throws -> PreparedTransaction2324 /// Send transaction25 /// - Parameter preparedTransaction: a prepared transaction26 /// - Returns: Transaction id27 func sendTransaction(28 preparedTransaction: PreparedTransaction29 ) async throws -> String3031 /// Simulate transaction32 /// - Parameter preparedTransaction: a prepared transaction33 func simulateTransaction(34 preparedTransaction: PreparedTransaction35 ) async throws -> SimulationResult36}3738public extension SolanaBlockchainClient {39 /// Send preparedTransaction40 /// - Parameter preparedTransaction: preparedTransaction to be sent41 /// - Returns: Transaction signature42 func sendTransaction(43 preparedTransaction: PreparedTransaction44 ) async throws -> String {45 try await Task.retrying(46 where: { $0.isEqualTo(.blockhashNotFound) },47 maxRetryCount: 3,48 retryDelay: 1,49 timeoutInSeconds: 6050 ) {51 let recentBlockhash = try await self.apiClient.getRecentBlockhash()52 let serializedTransaction = try self.signAndSerialize(53 preparedTransaction: preparedTransaction,54 recentBlockhash: recentBlockhash55 )56 return try await self.apiClient.sendTransaction(57 transaction: serializedTransaction,58 configs: RequestConfiguration(encoding: "base64")!59 )60 }61 .value62 }6364 /// Simulate transaction (for testing purpose)65 /// - Parameter preparedTransaction: preparedTransaction to be simulated66 /// - Returns: The result of Simulation67 func simulateTransaction(68 preparedTransaction: PreparedTransaction69 ) async throws -> SimulationResult {70 let recentBlockhash = try await apiClient.getRecentBlockhash()71 let serializedTransaction = try signAndSerialize(72 preparedTransaction: preparedTransaction,73 recentBlockhash: recentBlockhash74 )75 return try await apiClient.simulateTransaction(76 transaction: serializedTransaction, configs: RequestConfiguration(77 commitment: "confirmed",78 encoding: "base64",79 replaceRecentBlockhash: true80 )!81 )82 }8384 // MARK: - Helpers8586 /// Sign and serialize transaction (for testing purpose)87 /// - Parameters:88 /// - preparedTransaction: preparedTransaction89 /// - recentBlockhash: recentBlockhash90 /// - Returns: serializedTransaction91 internal func signAndSerialize(92 preparedTransaction: PreparedTransaction,93 recentBlockhash: String94 ) throws -> String {95 var preparedTransaction = preparedTransaction96 preparedTransaction.transaction.recentBlockhash = recentBlockhash97 try preparedTransaction.sign()98 return try preparedTransaction.serialize()99 }100}101