SPB Git

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%
2.3 KB · 60 lines swift
Raw Blame History
1import Foundation23public protocol FeeCalculator: AnyObject {4    func calculateNetworkFee(transaction: Transaction) throws -> FeeAmount5}67public class DefaultFeeCalculator: FeeCalculator {8    private let lamportsPerSignature: Lamports9    private let minRentExemption: Lamports1011    public init(lamportsPerSignature: Lamports, minRentExemption: Lamports) {12        self.lamportsPerSignature = lamportsPerSignature13        self.minRentExemption = minRentExemption14    }1516    public func calculateNetworkFee(transaction: Transaction) throws -> FeeAmount {17        let transactionFee = try transaction.calculateTransactionFee(lamportsPerSignatures: lamportsPerSignature)18        var accountCreationFee: Lamports = 019        var depositFee: Lamports = 020        for instruction in transaction.instructions {21            var createdAccount: PublicKey?22            switch instruction.programId {23            case SystemProgram.id:24                guard instruction.data.count >= 4 else { break }25                let index = UInt32(bytes: instruction.data[0 ..< 4])26                if index == SystemProgram.Index.create {27                    createdAccount = instruction.keys.last?.publicKey28                }29            case AssociatedTokenProgram.id:30                createdAccount = instruction.keys[safe: 1]?.publicKey31            default:32                break33            }3435            if let createdAccount = createdAccount {36                // Check if account is closed right after its creation37                let closingInstruction = transaction.instructions.first(38                    where: {39                        $0.data.first == TokenProgram.closeAccountIndex &&40                            $0.keys.first?.publicKey == createdAccount41                    }42                )43                let isAccountClosedAfterCreation = closingInstruction != nil4445                // If account is closed after creation, increase the deposit fee46                if isAccountClosedAfterCreation {47                    depositFee += minRentExemption48                }4950                // Otherwise, there will be an account creation fee51                else {52                    accountCreationFee += minRentExemption53                }54            }55        }5657        return .init(transaction: transactionFee, accountBalances: accountCreationFee, deposit: depositFee)58    }59}60