// This file was autogenerated by some hot garbage in the `uniffi` crate. // Trust me, you don't want to mess with it! import Foundation // Depending on the consumer's build setup, the low-level FFI code // might be in a separate module, or it might be compiled inline into // this module. This is a bit of light hackery to work with both. #if canImport(bdkFFI) import bdkFFI #endif fileprivate extension RustBuffer { // Allocate a new buffer, copying the contents of a `UInt8` array. init(bytes: [UInt8]) { let rbuf = bytes.withUnsafeBufferPointer { ptr in RustBuffer.from(ptr) } self.init(capacity: rbuf.capacity, len: rbuf.len, data: rbuf.data) } static func from(_ ptr: UnsafeBufferPointer) -> RustBuffer { try! rustCall { ffi_bdk_d04b_rustbuffer_from_bytes(ForeignBytes(bufferPointer: ptr), $0) } } // Frees the buffer in place. // The buffer must not be used after this is called. func deallocate() { try! rustCall { ffi_bdk_d04b_rustbuffer_free(self, $0) } } } fileprivate extension ForeignBytes { init(bufferPointer: UnsafeBufferPointer) { self.init(len: Int32(bufferPointer.count), data: bufferPointer.baseAddress) } } // For every type used in the interface, we provide helper methods for conveniently // lifting and lowering that type from C-compatible data, and for reading and writing // values of that type in a buffer. // Helper classes/extensions that don't change. // Someday, this will be in a libray of its own. fileprivate extension Data { init(rustBuffer: RustBuffer) { // TODO: This copies the buffer. Can we read directly from a // Rust buffer? self.init(bytes: rustBuffer.data!, count: Int(rustBuffer.len)) } } // A helper class to read values out of a byte buffer. fileprivate class Reader { let data: Data var offset: Data.Index init(data: Data) { self.data = data self.offset = 0 } // Reads an integer at the current offset, in big-endian order, and advances // the offset on success. Throws if reading the integer would move the // offset past the end of the buffer. func readInt() throws -> T { let range = offset...size guard data.count >= range.upperBound else { throw UniffiInternalError.bufferOverflow } if T.self == UInt8.self { let value = data[offset] offset += 1 return value as! T } var value: T = 0 let _ = withUnsafeMutableBytes(of: &value, { data.copyBytes(to: $0, from: range)}) offset = range.upperBound return value.bigEndian } // Reads an arbitrary number of bytes, to be used to read // raw bytes, this is useful when lifting strings func readBytes(count: Int) throws -> Array { let range = offset..<(offset+count) guard data.count >= range.upperBound else { throw UniffiInternalError.bufferOverflow } var value = [UInt8](repeating: 0, count: count) value.withUnsafeMutableBufferPointer({ buffer in data.copyBytes(to: buffer, from: range) }) offset = range.upperBound return value } // Reads a float at the current offset. @inlinable func readFloat() throws -> Float { return Float(bitPattern: try readInt()) } // Reads a float at the current offset. @inlinable func readDouble() throws -> Double { return Double(bitPattern: try readInt()) } // Indicates if the offset has reached the end of the buffer. @inlinable func hasRemaining() -> Bool { return offset < data.count } } // A helper class to write values into a byte buffer. fileprivate class Writer { var bytes: [UInt8] var offset: Array.Index init() { self.bytes = [] self.offset = 0 } func writeBytes(_ byteArr: S) where S: Sequence, S.Element == UInt8 { bytes.append(contentsOf: byteArr) } // Writes an integer in big-endian order. // // Warning: make sure what you are trying to write // is in the correct type! func writeInt(_ value: T) { var value = value.bigEndian withUnsafeBytes(of: &value) { bytes.append(contentsOf: $0) } } @inlinable func writeFloat(_ value: Float) { writeInt(value.bitPattern) } @inlinable func writeDouble(_ value: Double) { writeInt(value.bitPattern) } } // Types conforming to `Serializable` can be read and written in a bytebuffer. fileprivate protocol Serializable { func write(into: Writer) static func read(from: Reader) throws -> Self } // Types confirming to `ViaFfi` can be transferred back-and-for over the FFI. // This is analogous to the Rust trait of the same name. fileprivate protocol ViaFfi: Serializable { associatedtype FfiType static func lift(_ v: FfiType) throws -> Self func lower() -> FfiType } // Types conforming to `Primitive` pass themselves directly over the FFI. fileprivate protocol Primitive {} extension Primitive { fileprivate typealias FfiType = Self fileprivate static func lift(_ v: Self) throws -> Self { return v } fileprivate func lower() -> Self { return self } } // Types conforming to `ViaFfiUsingByteBuffer` lift and lower into a bytebuffer. // Use this for complex types where it's hard to write a custom lift/lower. fileprivate protocol ViaFfiUsingByteBuffer: Serializable {} extension ViaFfiUsingByteBuffer { fileprivate typealias FfiType = RustBuffer fileprivate static func lift(_ buf: FfiType) throws -> Self { let reader = Reader(data: Data(rustBuffer: buf)) let value = try Self.read(from: reader) if reader.hasRemaining() { throw UniffiInternalError.incompleteData } buf.deallocate() return value } fileprivate func lower() -> FfiType { let writer = Writer() self.write(into: writer) return RustBuffer(bytes: writer.bytes) } } // An error type for FFI errors. These errors occur at the UniFFI level, not // the library level. fileprivate enum UniffiInternalError: LocalizedError { case bufferOverflow case incompleteData case unexpectedOptionalTag case unexpectedEnumCase case unexpectedNullPointer case unexpectedRustCallStatusCode case unexpectedRustCallError case unexpectedStaleHandle case rustPanic(_ message: String) public var errorDescription: String? { switch self { case .bufferOverflow: return "Reading the requested value would read past the end of the buffer" case .incompleteData: return "The buffer still has data after lifting its containing value" case .unexpectedOptionalTag: return "Unexpected optional tag; should be 0 or 1" case .unexpectedEnumCase: return "Raw enum value doesn't match any cases" case .unexpectedNullPointer: return "Raw pointer value was null" case .unexpectedRustCallStatusCode: return "Unexpected RustCallStatus code" case .unexpectedRustCallError: return "CALL_ERROR but no errorClass specified" case .unexpectedStaleHandle: return "The object in the handle map has been dropped already" case let .rustPanic(message): return message } } } fileprivate let CALL_SUCCESS: Int8 = 0 fileprivate let CALL_ERROR: Int8 = 1 fileprivate let CALL_PANIC: Int8 = 2 fileprivate extension RustCallStatus { init() { self.init( code: CALL_SUCCESS, errorBuf: RustBuffer.init( capacity: 0, len: 0, data: nil ) ) } } private func rustCall(_ callback: (UnsafeMutablePointer) -> T) throws -> T { try makeRustCall(callback, errorHandler: { $0.deallocate() return UniffiInternalError.unexpectedRustCallError }) } private func rustCallWithError(_ errorClass: E.Type, _ callback: (UnsafeMutablePointer) -> T) throws -> T { try makeRustCall(callback, errorHandler: { return try E.lift($0) }) } private func makeRustCall(_ callback: (UnsafeMutablePointer) -> T, errorHandler: (RustBuffer) throws -> Error) throws -> T { var callStatus = RustCallStatus.init() let returnedVal = callback(&callStatus) switch callStatus.code { case CALL_SUCCESS: return returnedVal case CALL_ERROR: throw try errorHandler(callStatus.errorBuf) case CALL_PANIC: // When the rust code sees a panic, it tries to construct a RustBuffer // with the message. But if that code panics, then it just sends back // an empty buffer. if callStatus.errorBuf.len > 0 { throw UniffiInternalError.rustPanic(try String.lift(callStatus.errorBuf)) } else { callStatus.errorBuf.deallocate() throw UniffiInternalError.rustPanic("Rust panic") } default: throw UniffiInternalError.unexpectedRustCallStatusCode } } // Protocols for converters we'll implement in templates fileprivate protocol FfiConverter { associatedtype SwiftType associatedtype FfiType static func lift(_ ffiValue: FfiType) throws -> SwiftType static func lower(_ value: SwiftType) -> FfiType static func read(from: Reader) throws -> SwiftType static func write(_ value: SwiftType, into: Writer) } fileprivate protocol FfiConverterUsingByteBuffer: FfiConverter where FfiType == RustBuffer { // Empty, because we want to declare some helper methods in the extension below. } extension FfiConverterUsingByteBuffer { static func lower(_ value: SwiftType) -> FfiType { let writer = Writer() Self.write(value, into: writer) return RustBuffer(bytes: writer.bytes) } static func lift(_ buf: FfiType) throws -> SwiftType { let reader = Reader(data: Data(rustBuffer: buf)) let value = try Self.read(from: reader) if reader.hasRemaining() { throw UniffiInternalError.incompleteData } buf.deallocate() return value } } // Helpers for structural types. Note that because of canonical_names, it /should/ be impossible // to make another `FfiConverterSequence` etc just using the UDL. fileprivate enum FfiConverterSequence { static func write(_ value: [T], into buf: Writer, writeItem: (T, Writer) -> Void) { let len = Int32(value.count) buf.writeInt(len) for item in value { writeItem(item, buf) } } static func read(from buf: Reader, readItem: (Reader) throws -> T) throws -> [T] { let len: Int32 = try buf.readInt() var seq = [T]() seq.reserveCapacity(Int(len)) for _ in 0 ..< len { seq.append(try readItem(buf)) } return seq } } fileprivate enum FfiConverterOptional { static func write(_ value: T?, into buf: Writer, writeItem: (T, Writer) -> Void) { guard let value = value else { buf.writeInt(Int8(0)) return } buf.writeInt(Int8(1)) writeItem(value, buf) } static func read(from buf: Reader, readItem: (Reader) throws -> T) throws -> T? { switch try buf.readInt() as Int8 { case 0: return nil case 1: return try readItem(buf) default: throw UniffiInternalError.unexpectedOptionalTag } } } fileprivate enum FfiConverterDictionary { static func write(_ value: [String: T], into buf: Writer, writeItem: (String, T, Writer) -> Void) { let len = Int32(value.count) buf.writeInt(len) for (key, value) in value { writeItem(key, value, buf) } } static func read(from buf: Reader, readItem: (Reader) throws -> (String, T)) throws -> [String: T] { let len: Int32 = try buf.readInt() var dict = [String: T]() dict.reserveCapacity(Int(len)) for _ in 0..(f: () throws -> T) rethrows -> T { self.lock() defer { self.unlock() } return try f() } } fileprivate typealias Handle = UInt64 fileprivate class ConcurrentHandleMap { private var leftMap: [Handle: T] = [:] private var counter: [Handle: UInt64] = [:] private var rightMap: [ObjectIdentifier: Handle] = [:] private let lock = NSLock() private var currentHandle: Handle = 0 private let stride: Handle = 1 func insert(obj: T) -> Handle { lock.withLock { let id = ObjectIdentifier(obj as AnyObject) let handle = rightMap[id] ?? { currentHandle += stride let handle = currentHandle leftMap[handle] = obj rightMap[id] = handle return handle }() counter[handle] = (counter[handle] ?? 0) + 1 return handle } } func get(handle: Handle) -> T? { lock.withLock { leftMap[handle] } } func delete(handle: Handle) { remove(handle: handle) } @discardableResult func remove(handle: Handle) -> T? { lock.withLock { defer { counter[handle] = (counter[handle] ?? 1) - 1 } guard counter[handle] == 1 else { return leftMap[handle] } let obj = leftMap.removeValue(forKey: handle) if let obj = obj { rightMap.removeValue(forKey: ObjectIdentifier(obj as AnyObject)) } return obj } } } // Magic number for the Rust proxy to call using the same mechanism as every other method, // to free the callback once it's dropped by Rust. private let IDX_CALLBACK_FREE: Int32 = 0 fileprivate class FfiConverterCallbackInterface { fileprivate let handleMap = ConcurrentHandleMap() func drop(handle: Handle) { handleMap.remove(handle: handle) } func lift(_ handle: Handle) throws -> CallbackInterface { guard let callback = handleMap.get(handle: handle) else { throw UniffiInternalError.unexpectedStaleHandle } return callback } func read(from buf: Reader) throws -> CallbackInterface { let handle: Handle = try buf.readInt() return try lift(handle) } func lower(_ v: CallbackInterface) -> Handle { let handle = handleMap.insert(obj: v) return handle // assert(handleMap.get(handle: obj) == v, "Handle map is not returning the object we just placed there. This is a bug in the HandleMap.") } func write(_ v: CallbackInterface, into buf: Writer) { buf.writeInt(lower(v)) } } // Note that we don't yet support `indirect` for enums. // See https://github.com/mozilla/uniffi-rs/issues/396 for further discussion. public enum Network { case bitcoin case testnet case signet case regtest } extension Network: ViaFfiUsingByteBuffer, ViaFfi { fileprivate static func read(from buf: Reader) throws -> Network { let variant: Int32 = try buf.readInt() switch variant { case 1: return .bitcoin case 2: return .testnet case 3: return .signet case 4: return .regtest default: throw UniffiInternalError.unexpectedEnumCase } } fileprivate func write(into buf: Writer) { switch self { case .bitcoin: buf.writeInt(Int32(1)) case .testnet: buf.writeInt(Int32(2)) case .signet: buf.writeInt(Int32(3)) case .regtest: buf.writeInt(Int32(4)) } } } extension Network: Equatable, Hashable {} // Note that we don't yet support `indirect` for enums. // See https://github.com/mozilla/uniffi-rs/issues/396 for further discussion. public enum DatabaseConfig { case memory(junk: String ) case sled(config: SledDbConfiguration ) } extension DatabaseConfig: ViaFfiUsingByteBuffer, ViaFfi { fileprivate static func read(from buf: Reader) throws -> DatabaseConfig { let variant: Int32 = try buf.readInt() switch variant { case 1: return .memory( junk: try String.read(from: buf) ) case 2: return .sled( config: try SledDbConfiguration.read(from: buf) ) default: throw UniffiInternalError.unexpectedEnumCase } } fileprivate func write(into buf: Writer) { switch self { case let .memory(junk): buf.writeInt(Int32(1)) junk.write(into: buf) case let .sled(config): buf.writeInt(Int32(2)) config.write(into: buf) } } } extension DatabaseConfig: Equatable, Hashable {} // Note that we don't yet support `indirect` for enums. // See https://github.com/mozilla/uniffi-rs/issues/396 for further discussion. public enum Transaction { case unconfirmed(details: TransactionDetails ) case confirmed(details: TransactionDetails, confirmation: BlockTime ) } extension Transaction: ViaFfiUsingByteBuffer, ViaFfi { fileprivate static func read(from buf: Reader) throws -> Transaction { let variant: Int32 = try buf.readInt() switch variant { case 1: return .unconfirmed( details: try TransactionDetails.read(from: buf) ) case 2: return .confirmed( details: try TransactionDetails.read(from: buf), confirmation: try BlockTime.read(from: buf) ) default: throw UniffiInternalError.unexpectedEnumCase } } fileprivate func write(into buf: Writer) { switch self { case let .unconfirmed(details): buf.writeInt(Int32(1)) details.write(into: buf) case let .confirmed(details,confirmation): buf.writeInt(Int32(2)) details.write(into: buf) confirmation.write(into: buf) } } } extension Transaction: Equatable, Hashable {} // Note that we don't yet support `indirect` for enums. // See https://github.com/mozilla/uniffi-rs/issues/396 for further discussion. public enum BlockchainConfig { case electrum(config: ElectrumConfig ) case esplora(config: EsploraConfig ) } extension BlockchainConfig: ViaFfiUsingByteBuffer, ViaFfi { fileprivate static func read(from buf: Reader) throws -> BlockchainConfig { let variant: Int32 = try buf.readInt() switch variant { case 1: return .electrum( config: try ElectrumConfig.read(from: buf) ) case 2: return .esplora( config: try EsploraConfig.read(from: buf) ) default: throw UniffiInternalError.unexpectedEnumCase } } fileprivate func write(into buf: Writer) { switch self { case let .electrum(config): buf.writeInt(Int32(1)) config.write(into: buf) case let .esplora(config): buf.writeInt(Int32(2)) config.write(into: buf) } } } extension BlockchainConfig: Equatable, Hashable {} // Note that we don't yet support `indirect` for enums. // See https://github.com/mozilla/uniffi-rs/issues/396 for further discussion. public enum WordCount { case words12 case words15 case words18 case words21 case words24 } extension WordCount: ViaFfiUsingByteBuffer, ViaFfi { fileprivate static func read(from buf: Reader) throws -> WordCount { let variant: Int32 = try buf.readInt() switch variant { case 1: return .words12 case 2: return .words15 case 3: return .words18 case 4: return .words21 case 5: return .words24 default: throw UniffiInternalError.unexpectedEnumCase } } fileprivate func write(into buf: Writer) { switch self { case .words12: buf.writeInt(Int32(1)) case .words15: buf.writeInt(Int32(2)) case .words18: buf.writeInt(Int32(3)) case .words21: buf.writeInt(Int32(4)) case .words24: buf.writeInt(Int32(5)) } } } extension WordCount: Equatable, Hashable {} public func generateExtendedKey( network: Network, wordCount: WordCount, password: String? ) throws -> ExtendedKeyInfo { let _retval = try rustCallWithError(BdkError.self) { bdk_d04b_generate_extended_key(network.lower(), wordCount.lower(), FfiConverterOptionString.lower(password) , $0) } return try ExtendedKeyInfo.lift(_retval) } public func restoreExtendedKey( network: Network, mnemonic: String, password: String? ) throws -> ExtendedKeyInfo { let _retval = try rustCallWithError(BdkError.self) { bdk_d04b_restore_extended_key(network.lower(), mnemonic.lower(), FfiConverterOptionString.lower(password) , $0) } return try ExtendedKeyInfo.lift(_retval) } public protocol WalletProtocol { func getNewAddress() -> String func getLastUnusedAddress() -> String func getBalance() throws -> UInt64 func sign( psbt: PartiallySignedBitcoinTransaction ) throws func getTransactions() throws -> [Transaction] func getNetwork() -> Network func sync( progressUpdate: BdkProgress, maxAddressParam: UInt32? ) throws func broadcast( psbt: PartiallySignedBitcoinTransaction ) throws -> Transaction } public class Wallet: WalletProtocol { fileprivate let pointer: UnsafeMutableRawPointer // TODO: We'd like this to be `private` but for Swifty reasons, // we can't implement `ViaFfi` without making this `required` and we can't // make it `required` without making it `public`. required init(unsafeFromRawPointer pointer: UnsafeMutableRawPointer) { self.pointer = pointer } public convenience init( descriptor: String, changeDescriptor: String?, network: Network, databaseConfig: DatabaseConfig, blockchainConfig: BlockchainConfig ) throws { self.init(unsafeFromRawPointer: try rustCallWithError(BdkError.self) { bdk_d04b_Wallet_new(descriptor.lower(), FfiConverterOptionString.lower(changeDescriptor), network.lower(), databaseConfig.lower(), blockchainConfig.lower() , $0) }) } deinit { try! rustCall { ffi_bdk_d04b_Wallet_object_free(pointer, $0) } } public func getNewAddress() -> String { let _retval = try! rustCall() { bdk_d04b_Wallet_get_new_address(self.pointer, $0 ) } return try! String.lift(_retval) } public func getLastUnusedAddress() -> String { let _retval = try! rustCall() { bdk_d04b_Wallet_get_last_unused_address(self.pointer, $0 ) } return try! String.lift(_retval) } public func getBalance() throws -> UInt64 { let _retval = try rustCallWithError(BdkError.self) { bdk_d04b_Wallet_get_balance(self.pointer, $0 ) } return try UInt64.lift(_retval) } public func sign( psbt: PartiallySignedBitcoinTransaction ) throws { try rustCallWithError(BdkError.self) { bdk_d04b_Wallet_sign(self.pointer, psbt.lower() , $0 ) } } public func getTransactions() throws -> [Transaction] { let _retval = try rustCallWithError(BdkError.self) { bdk_d04b_Wallet_get_transactions(self.pointer, $0 ) } return try FfiConverterSequenceEnumTransaction.lift(_retval) } public func getNetwork() -> Network { let _retval = try! rustCall() { bdk_d04b_Wallet_get_network(self.pointer, $0 ) } return try! Network.lift(_retval) } public func sync( progressUpdate: BdkProgress, maxAddressParam: UInt32? ) throws { try rustCallWithError(BdkError.self) { bdk_d04b_Wallet_sync(self.pointer, ffiConverterCallbackInterfaceBdkProgress.lower(progressUpdate), FfiConverterOptionUInt32.lower(maxAddressParam) , $0 ) } } public func broadcast( psbt: PartiallySignedBitcoinTransaction ) throws -> Transaction { let _retval = try rustCallWithError(BdkError.self) { bdk_d04b_Wallet_broadcast(self.pointer, psbt.lower() , $0 ) } return try Transaction.lift(_retval) } } fileprivate extension Wallet { typealias FfiType = UnsafeMutableRawPointer static func read(from buf: Reader) throws -> Self { let v: UInt64 = try buf.readInt() // The Rust code won't compile if a pointer won't fit in a UInt64. // We have to go via `UInt` because that's the thing that's the size of a pointer. let ptr = UnsafeMutableRawPointer(bitPattern: UInt(truncatingIfNeeded: v)) if (ptr == nil) { throw UniffiInternalError.unexpectedNullPointer } return try self.lift(ptr!) } func write(into buf: Writer) { // This fiddling is because `Int` is the thing that's the same size as a pointer. // The Rust code won't compile if a pointer won't fit in a `UInt64`. buf.writeInt(UInt64(bitPattern: Int64(Int(bitPattern: self.lower())))) } static func lift(_ pointer: UnsafeMutableRawPointer) throws -> Self { return Self(unsafeFromRawPointer: pointer) } func lower() -> UnsafeMutableRawPointer { return self.pointer } } // Ideally this would be `fileprivate`, but Swift says: // """ // 'private' modifier cannot be used with extensions that declare protocol conformances // """ extension Wallet : ViaFfi, Serializable {} public protocol PartiallySignedBitcoinTransactionProtocol { func serialize() -> String } public class PartiallySignedBitcoinTransaction: PartiallySignedBitcoinTransactionProtocol { fileprivate let pointer: UnsafeMutableRawPointer // TODO: We'd like this to be `private` but for Swifty reasons, // we can't implement `ViaFfi` without making this `required` and we can't // make it `required` without making it `public`. required init(unsafeFromRawPointer pointer: UnsafeMutableRawPointer) { self.pointer = pointer } public convenience init( wallet: Wallet, recipient: String, amount: UInt64, feeRate: Float? ) throws { self.init(unsafeFromRawPointer: try rustCallWithError(BdkError.self) { bdk_d04b_PartiallySignedBitcoinTransaction_new(wallet.lower(), recipient.lower(), amount.lower(), FfiConverterOptionFloat.lower(feeRate) , $0) }) } deinit { try! rustCall { ffi_bdk_d04b_PartiallySignedBitcoinTransaction_object_free(pointer, $0) } } public static func deserialize( psbtBase64: String ) throws -> PartiallySignedBitcoinTransaction { return PartiallySignedBitcoinTransaction(unsafeFromRawPointer: try rustCallWithError(BdkError.self) { bdk_d04b_PartiallySignedBitcoinTransaction_deserialize(psbtBase64.lower() , $0) }) } public func serialize() -> String { let _retval = try! rustCall() { bdk_d04b_PartiallySignedBitcoinTransaction_serialize(self.pointer, $0 ) } return try! String.lift(_retval) } } fileprivate extension PartiallySignedBitcoinTransaction { typealias FfiType = UnsafeMutableRawPointer static func read(from buf: Reader) throws -> Self { let v: UInt64 = try buf.readInt() // The Rust code won't compile if a pointer won't fit in a UInt64. // We have to go via `UInt` because that's the thing that's the size of a pointer. let ptr = UnsafeMutableRawPointer(bitPattern: UInt(truncatingIfNeeded: v)) if (ptr == nil) { throw UniffiInternalError.unexpectedNullPointer } return try self.lift(ptr!) } func write(into buf: Writer) { // This fiddling is because `Int` is the thing that's the same size as a pointer. // The Rust code won't compile if a pointer won't fit in a `UInt64`. buf.writeInt(UInt64(bitPattern: Int64(Int(bitPattern: self.lower())))) } static func lift(_ pointer: UnsafeMutableRawPointer) throws -> Self { return Self(unsafeFromRawPointer: pointer) } func lower() -> UnsafeMutableRawPointer { return self.pointer } } // Ideally this would be `fileprivate`, but Swift says: // """ // 'private' modifier cannot be used with extensions that declare protocol conformances // """ extension PartiallySignedBitcoinTransaction : ViaFfi, Serializable {} public struct SledDbConfiguration { public var path: String public var treeName: String // Default memberwise initializers are never public by default, so we // declare one manually. public init(path: String, treeName: String ) { self.path = path self.treeName = treeName } } extension SledDbConfiguration: Equatable, Hashable { public static func ==(lhs: SledDbConfiguration, rhs: SledDbConfiguration) -> Bool { if lhs.path != rhs.path { return false } if lhs.treeName != rhs.treeName { return false } return true } public func hash(into hasher: inout Hasher) { hasher.combine(path) hasher.combine(treeName) } } fileprivate extension SledDbConfiguration { static func read(from buf: Reader) throws -> SledDbConfiguration { return try SledDbConfiguration( path: String.read(from: buf), treeName: String.read(from: buf) ) } func write(into buf: Writer) { self.path.write(into: buf) self.treeName.write(into: buf) } } extension SledDbConfiguration: ViaFfiUsingByteBuffer, ViaFfi {} public struct TransactionDetails { public var fees: UInt64? public var received: UInt64 public var sent: UInt64 public var txid: String // Default memberwise initializers are never public by default, so we // declare one manually. public init(fees: UInt64?, received: UInt64, sent: UInt64, txid: String ) { self.fees = fees self.received = received self.sent = sent self.txid = txid } } extension TransactionDetails: Equatable, Hashable { public static func ==(lhs: TransactionDetails, rhs: TransactionDetails) -> Bool { if lhs.fees != rhs.fees { return false } if lhs.received != rhs.received { return false } if lhs.sent != rhs.sent { return false } if lhs.txid != rhs.txid { return false } return true } public func hash(into hasher: inout Hasher) { hasher.combine(fees) hasher.combine(received) hasher.combine(sent) hasher.combine(txid) } } fileprivate extension TransactionDetails { static func read(from buf: Reader) throws -> TransactionDetails { return try TransactionDetails( fees: FfiConverterOptionUInt64.read(from: buf), received: UInt64.read(from: buf), sent: UInt64.read(from: buf), txid: String.read(from: buf) ) } func write(into buf: Writer) { FfiConverterOptionUInt64.write(self.fees, into: buf) self.received.write(into: buf) self.sent.write(into: buf) self.txid.write(into: buf) } } extension TransactionDetails: ViaFfiUsingByteBuffer, ViaFfi {} public struct BlockTime { public var height: UInt32 public var timestamp: UInt64 // Default memberwise initializers are never public by default, so we // declare one manually. public init(height: UInt32, timestamp: UInt64 ) { self.height = height self.timestamp = timestamp } } extension BlockTime: Equatable, Hashable { public static func ==(lhs: BlockTime, rhs: BlockTime) -> Bool { if lhs.height != rhs.height { return false } if lhs.timestamp != rhs.timestamp { return false } return true } public func hash(into hasher: inout Hasher) { hasher.combine(height) hasher.combine(timestamp) } } fileprivate extension BlockTime { static func read(from buf: Reader) throws -> BlockTime { return try BlockTime( height: UInt32.read(from: buf), timestamp: UInt64.read(from: buf) ) } func write(into buf: Writer) { self.height.write(into: buf) self.timestamp.write(into: buf) } } extension BlockTime: ViaFfiUsingByteBuffer, ViaFfi {} public struct ElectrumConfig { public var url: String public var socks5: String? public var retry: UInt8 public var timeout: UInt8? public var stopGap: UInt64 // Default memberwise initializers are never public by default, so we // declare one manually. public init(url: String, socks5: String?, retry: UInt8, timeout: UInt8?, stopGap: UInt64 ) { self.url = url self.socks5 = socks5 self.retry = retry self.timeout = timeout self.stopGap = stopGap } } extension ElectrumConfig: Equatable, Hashable { public static func ==(lhs: ElectrumConfig, rhs: ElectrumConfig) -> Bool { if lhs.url != rhs.url { return false } if lhs.socks5 != rhs.socks5 { return false } if lhs.retry != rhs.retry { return false } if lhs.timeout != rhs.timeout { return false } if lhs.stopGap != rhs.stopGap { return false } return true } public func hash(into hasher: inout Hasher) { hasher.combine(url) hasher.combine(socks5) hasher.combine(retry) hasher.combine(timeout) hasher.combine(stopGap) } } fileprivate extension ElectrumConfig { static func read(from buf: Reader) throws -> ElectrumConfig { return try ElectrumConfig( url: String.read(from: buf), socks5: FfiConverterOptionString.read(from: buf), retry: UInt8.read(from: buf), timeout: FfiConverterOptionUInt8.read(from: buf), stopGap: UInt64.read(from: buf) ) } func write(into buf: Writer) { self.url.write(into: buf) FfiConverterOptionString.write(self.socks5, into: buf) self.retry.write(into: buf) FfiConverterOptionUInt8.write(self.timeout, into: buf) self.stopGap.write(into: buf) } } extension ElectrumConfig: ViaFfiUsingByteBuffer, ViaFfi {} public struct EsploraConfig { public var baseUrl: String public var proxy: String? public var timeoutRead: UInt64 public var timeoutWrite: UInt64 public var stopGap: UInt64 // Default memberwise initializers are never public by default, so we // declare one manually. public init(baseUrl: String, proxy: String?, timeoutRead: UInt64, timeoutWrite: UInt64, stopGap: UInt64 ) { self.baseUrl = baseUrl self.proxy = proxy self.timeoutRead = timeoutRead self.timeoutWrite = timeoutWrite self.stopGap = stopGap } } extension EsploraConfig: Equatable, Hashable { public static func ==(lhs: EsploraConfig, rhs: EsploraConfig) -> Bool { if lhs.baseUrl != rhs.baseUrl { return false } if lhs.proxy != rhs.proxy { return false } if lhs.timeoutRead != rhs.timeoutRead { return false } if lhs.timeoutWrite != rhs.timeoutWrite { return false } if lhs.stopGap != rhs.stopGap { return false } return true } public func hash(into hasher: inout Hasher) { hasher.combine(baseUrl) hasher.combine(proxy) hasher.combine(timeoutRead) hasher.combine(timeoutWrite) hasher.combine(stopGap) } } fileprivate extension EsploraConfig { static func read(from buf: Reader) throws -> EsploraConfig { return try EsploraConfig( baseUrl: String.read(from: buf), proxy: FfiConverterOptionString.read(from: buf), timeoutRead: UInt64.read(from: buf), timeoutWrite: UInt64.read(from: buf), stopGap: UInt64.read(from: buf) ) } func write(into buf: Writer) { self.baseUrl.write(into: buf) FfiConverterOptionString.write(self.proxy, into: buf) self.timeoutRead.write(into: buf) self.timeoutWrite.write(into: buf) self.stopGap.write(into: buf) } } extension EsploraConfig: ViaFfiUsingByteBuffer, ViaFfi {} public struct ExtendedKeyInfo { public var mnemonic: String public var xprv: String public var fingerprint: String // Default memberwise initializers are never public by default, so we // declare one manually. public init(mnemonic: String, xprv: String, fingerprint: String ) { self.mnemonic = mnemonic self.xprv = xprv self.fingerprint = fingerprint } } extension ExtendedKeyInfo: Equatable, Hashable { public static func ==(lhs: ExtendedKeyInfo, rhs: ExtendedKeyInfo) -> Bool { if lhs.mnemonic != rhs.mnemonic { return false } if lhs.xprv != rhs.xprv { return false } if lhs.fingerprint != rhs.fingerprint { return false } return true } public func hash(into hasher: inout Hasher) { hasher.combine(mnemonic) hasher.combine(xprv) hasher.combine(fingerprint) } } fileprivate extension ExtendedKeyInfo { static func read(from buf: Reader) throws -> ExtendedKeyInfo { return try ExtendedKeyInfo( mnemonic: String.read(from: buf), xprv: String.read(from: buf), fingerprint: String.read(from: buf) ) } func write(into buf: Writer) { self.mnemonic.write(into: buf) self.xprv.write(into: buf) self.fingerprint.write(into: buf) } } extension ExtendedKeyInfo: ViaFfiUsingByteBuffer, ViaFfi {} public enum BdkError { // Simple error enums only carry a message case InvalidU32Bytes(message: String) // Simple error enums only carry a message case Generic(message: String) // Simple error enums only carry a message case ScriptDoesntHaveAddressForm(message: String) // Simple error enums only carry a message case NoRecipients(message: String) // Simple error enums only carry a message case NoUtxosSelected(message: String) // Simple error enums only carry a message case OutputBelowDustLimit(message: String) // Simple error enums only carry a message case InsufficientFunds(message: String) // Simple error enums only carry a message case BnBTotalTriesExceeded(message: String) // Simple error enums only carry a message case BnBNoExactMatch(message: String) // Simple error enums only carry a message case UnknownUtxo(message: String) // Simple error enums only carry a message case TransactionNotFound(message: String) // Simple error enums only carry a message case TransactionConfirmed(message: String) // Simple error enums only carry a message case IrreplaceableTransaction(message: String) // Simple error enums only carry a message case FeeRateTooLow(message: String) // Simple error enums only carry a message case FeeTooLow(message: String) // Simple error enums only carry a message case FeeRateUnavailable(message: String) // Simple error enums only carry a message case MissingKeyOrigin(message: String) // Simple error enums only carry a message case Key(message: String) // Simple error enums only carry a message case ChecksumMismatch(message: String) // Simple error enums only carry a message case SpendingPolicyRequired(message: String) // Simple error enums only carry a message case InvalidPolicyPathError(message: String) // Simple error enums only carry a message case Signer(message: String) // Simple error enums only carry a message case InvalidNetwork(message: String) // Simple error enums only carry a message case InvalidProgressValue(message: String) // Simple error enums only carry a message case ProgressUpdateError(message: String) // Simple error enums only carry a message case InvalidOutpoint(message: String) // Simple error enums only carry a message case Descriptor(message: String) // Simple error enums only carry a message case AddressValidator(message: String) // Simple error enums only carry a message case Encode(message: String) // Simple error enums only carry a message case Miniscript(message: String) // Simple error enums only carry a message case Bip32(message: String) // Simple error enums only carry a message case Secp256k1(message: String) // Simple error enums only carry a message case Json(message: String) // Simple error enums only carry a message case Hex(message: String) // Simple error enums only carry a message case Psbt(message: String) // Simple error enums only carry a message case PsbtParse(message: String) // Simple error enums only carry a message case Electrum(message: String) // Simple error enums only carry a message case Esplora(message: String) // Simple error enums only carry a message case Sled(message: String) } extension BdkError: ViaFfiUsingByteBuffer, ViaFfi { fileprivate static func read(from buf: Reader) throws -> BdkError { let variant: Int32 = try buf.readInt() switch variant { case 1: return .InvalidU32Bytes( message: try String.read(from: buf) ) case 2: return .Generic( message: try String.read(from: buf) ) case 3: return .ScriptDoesntHaveAddressForm( message: try String.read(from: buf) ) case 4: return .NoRecipients( message: try String.read(from: buf) ) case 5: return .NoUtxosSelected( message: try String.read(from: buf) ) case 6: return .OutputBelowDustLimit( message: try String.read(from: buf) ) case 7: return .InsufficientFunds( message: try String.read(from: buf) ) case 8: return .BnBTotalTriesExceeded( message: try String.read(from: buf) ) case 9: return .BnBNoExactMatch( message: try String.read(from: buf) ) case 10: return .UnknownUtxo( message: try String.read(from: buf) ) case 11: return .TransactionNotFound( message: try String.read(from: buf) ) case 12: return .TransactionConfirmed( message: try String.read(from: buf) ) case 13: return .IrreplaceableTransaction( message: try String.read(from: buf) ) case 14: return .FeeRateTooLow( message: try String.read(from: buf) ) case 15: return .FeeTooLow( message: try String.read(from: buf) ) case 16: return .FeeRateUnavailable( message: try String.read(from: buf) ) case 17: return .MissingKeyOrigin( message: try String.read(from: buf) ) case 18: return .Key( message: try String.read(from: buf) ) case 19: return .ChecksumMismatch( message: try String.read(from: buf) ) case 20: return .SpendingPolicyRequired( message: try String.read(from: buf) ) case 21: return .InvalidPolicyPathError( message: try String.read(from: buf) ) case 22: return .Signer( message: try String.read(from: buf) ) case 23: return .InvalidNetwork( message: try String.read(from: buf) ) case 24: return .InvalidProgressValue( message: try String.read(from: buf) ) case 25: return .ProgressUpdateError( message: try String.read(from: buf) ) case 26: return .InvalidOutpoint( message: try String.read(from: buf) ) case 27: return .Descriptor( message: try String.read(from: buf) ) case 28: return .AddressValidator( message: try String.read(from: buf) ) case 29: return .Encode( message: try String.read(from: buf) ) case 30: return .Miniscript( message: try String.read(from: buf) ) case 31: return .Bip32( message: try String.read(from: buf) ) case 32: return .Secp256k1( message: try String.read(from: buf) ) case 33: return .Json( message: try String.read(from: buf) ) case 34: return .Hex( message: try String.read(from: buf) ) case 35: return .Psbt( message: try String.read(from: buf) ) case 36: return .PsbtParse( message: try String.read(from: buf) ) case 37: return .Electrum( message: try String.read(from: buf) ) case 38: return .Esplora( message: try String.read(from: buf) ) case 39: return .Sled( message: try String.read(from: buf) ) default: throw UniffiInternalError.unexpectedEnumCase } } fileprivate func write(into buf: Writer) { switch self { case let .InvalidU32Bytes(message): buf.writeInt(Int32(1)) message.write(into: buf) case let .Generic(message): buf.writeInt(Int32(2)) message.write(into: buf) case let .ScriptDoesntHaveAddressForm(message): buf.writeInt(Int32(3)) message.write(into: buf) case let .NoRecipients(message): buf.writeInt(Int32(4)) message.write(into: buf) case let .NoUtxosSelected(message): buf.writeInt(Int32(5)) message.write(into: buf) case let .OutputBelowDustLimit(message): buf.writeInt(Int32(6)) message.write(into: buf) case let .InsufficientFunds(message): buf.writeInt(Int32(7)) message.write(into: buf) case let .BnBTotalTriesExceeded(message): buf.writeInt(Int32(8)) message.write(into: buf) case let .BnBNoExactMatch(message): buf.writeInt(Int32(9)) message.write(into: buf) case let .UnknownUtxo(message): buf.writeInt(Int32(10)) message.write(into: buf) case let .TransactionNotFound(message): buf.writeInt(Int32(11)) message.write(into: buf) case let .TransactionConfirmed(message): buf.writeInt(Int32(12)) message.write(into: buf) case let .IrreplaceableTransaction(message): buf.writeInt(Int32(13)) message.write(into: buf) case let .FeeRateTooLow(message): buf.writeInt(Int32(14)) message.write(into: buf) case let .FeeTooLow(message): buf.writeInt(Int32(15)) message.write(into: buf) case let .FeeRateUnavailable(message): buf.writeInt(Int32(16)) message.write(into: buf) case let .MissingKeyOrigin(message): buf.writeInt(Int32(17)) message.write(into: buf) case let .Key(message): buf.writeInt(Int32(18)) message.write(into: buf) case let .ChecksumMismatch(message): buf.writeInt(Int32(19)) message.write(into: buf) case let .SpendingPolicyRequired(message): buf.writeInt(Int32(20)) message.write(into: buf) case let .InvalidPolicyPathError(message): buf.writeInt(Int32(21)) message.write(into: buf) case let .Signer(message): buf.writeInt(Int32(22)) message.write(into: buf) case let .InvalidNetwork(message): buf.writeInt(Int32(23)) message.write(into: buf) case let .InvalidProgressValue(message): buf.writeInt(Int32(24)) message.write(into: buf) case let .ProgressUpdateError(message): buf.writeInt(Int32(25)) message.write(into: buf) case let .InvalidOutpoint(message): buf.writeInt(Int32(26)) message.write(into: buf) case let .Descriptor(message): buf.writeInt(Int32(27)) message.write(into: buf) case let .AddressValidator(message): buf.writeInt(Int32(28)) message.write(into: buf) case let .Encode(message): buf.writeInt(Int32(29)) message.write(into: buf) case let .Miniscript(message): buf.writeInt(Int32(30)) message.write(into: buf) case let .Bip32(message): buf.writeInt(Int32(31)) message.write(into: buf) case let .Secp256k1(message): buf.writeInt(Int32(32)) message.write(into: buf) case let .Json(message): buf.writeInt(Int32(33)) message.write(into: buf) case let .Hex(message): buf.writeInt(Int32(34)) message.write(into: buf) case let .Psbt(message): buf.writeInt(Int32(35)) message.write(into: buf) case let .PsbtParse(message): buf.writeInt(Int32(36)) message.write(into: buf) case let .Electrum(message): buf.writeInt(Int32(37)) message.write(into: buf) case let .Esplora(message): buf.writeInt(Int32(38)) message.write(into: buf) case let .Sled(message): buf.writeInt(Int32(39)) message.write(into: buf) } } } extension BdkError: Equatable, Hashable {} extension BdkError: Error { } // Declaration and FfiConverters for BdkProgress Callback Interface public protocol BdkProgress : AnyObject { func update( progress: Float, message: String? ) } // The ForeignCallback that is passed to Rust. fileprivate let foreignCallbackCallbackInterfaceBdkProgress : ForeignCallback = { (handle: Handle, method: Int32, args: RustBuffer, out_buf: UnsafeMutablePointer) -> Int32 in func invokeUpdate(_ swiftCallbackInterface: BdkProgress, _ args: RustBuffer) throws -> RustBuffer { defer { args.deallocate() } let reader = Reader(data: Data(rustBuffer: args)) swiftCallbackInterface.update( progress: try Float.read(from: reader), message: try FfiConverterOptionString.read(from: reader) ) return RustBuffer() // TODO catch errors and report them back to Rust. // https://github.com/mozilla/uniffi-rs/issues/351 } let cb = try! ffiConverterCallbackInterfaceBdkProgress.lift(handle) switch method { case IDX_CALLBACK_FREE: ffiConverterCallbackInterfaceBdkProgress.drop(handle: handle) // No return value. // See docs of ForeignCallback in `uniffi/src/ffi/foreigncallbacks.rs` return 0 case 1: let buffer = try! invokeUpdate(cb, args) out_buf.pointee = buffer // Value written to out buffer. // See docs of ForeignCallback in `uniffi/src/ffi/foreigncallbacks.rs` return 1 // This should never happen, because an out of bounds method index won't // ever be used. Once we can catch errors, we should return an InternalError. // https://github.com/mozilla/uniffi-rs/issues/351 default: // An unexpected error happened. // See docs of ForeignCallback in `uniffi/src/ffi/foreigncallbacks.rs` return -1 } } // The ffiConverter which transforms the Callbacks in to Handles to pass to Rust. private let ffiConverterCallbackInterfaceBdkProgress: FfiConverterCallbackInterface = { try! rustCall { (err: UnsafeMutablePointer) in ffi_bdk_d04b_BdkProgress_init_callback(foreignCallbackCallbackInterfaceBdkProgress, err) } return FfiConverterCallbackInterface() }() extension UInt8: Primitive, ViaFfi { fileprivate static func read(from buf: Reader) throws -> Self { return try self.lift(buf.readInt()) } fileprivate func write(into buf: Writer) { buf.writeInt(self.lower()) } } extension UInt32: Primitive, ViaFfi { fileprivate static func read(from buf: Reader) throws -> Self { return try self.lift(buf.readInt()) } fileprivate func write(into buf: Writer) { buf.writeInt(self.lower()) } } extension UInt64: Primitive, ViaFfi { fileprivate static func read(from buf: Reader) throws -> Self { return try self.lift(buf.readInt()) } fileprivate func write(into buf: Writer) { buf.writeInt(self.lower()) } } extension Float: Primitive, ViaFfi { fileprivate static func read(from buf: Reader) throws -> Self { return try self.lift(buf.readFloat()) } fileprivate func write(into buf: Writer) { buf.writeFloat(self.lower()) } } extension String: ViaFfi { fileprivate typealias FfiType = RustBuffer fileprivate static func lift(_ v: FfiType) throws -> Self { defer { v.deallocate() } if v.data == nil { return String() } let bytes = UnsafeBufferPointer(start: v.data!, count: Int(v.len)) return String(bytes: bytes, encoding: String.Encoding.utf8)! } fileprivate func lower() -> FfiType { return self.utf8CString.withUnsafeBufferPointer { ptr in // The swift string gives us int8_t, we want uint8_t. ptr.withMemoryRebound(to: UInt8.self) { ptr in // The swift string gives us a trailing null byte, we don't want it. let buf = UnsafeBufferPointer(rebasing: ptr.prefix(upTo: ptr.count - 1)) return RustBuffer.from(buf) } } } fileprivate static func read(from buf: Reader) throws -> Self { let len: Int32 = try buf.readInt() return String(bytes: try buf.readBytes(count: Int(len)), encoding: String.Encoding.utf8)! } fileprivate func write(into buf: Writer) { let len = Int32(self.utf8.count) buf.writeInt(len) buf.writeBytes(self.utf8) } } // Helper code for PartiallySignedBitcoinTransaction class is found in ObjectTemplate.swift // Helper code for Wallet class is found in ObjectTemplate.swift // Helper code for BlockTime record is found in RecordTemplate.swift // Helper code for ElectrumConfig record is found in RecordTemplate.swift // Helper code for EsploraConfig record is found in RecordTemplate.swift // Helper code for ExtendedKeyInfo record is found in RecordTemplate.swift // Helper code for SledDbConfiguration record is found in RecordTemplate.swift // Helper code for TransactionDetails record is found in RecordTemplate.swift // Helper code for BlockchainConfig enum is found in EnumTemplate.swift // Helper code for DatabaseConfig enum is found in EnumTemplate.swift // Helper code for Network enum is found in EnumTemplate.swift // Helper code for Transaction enum is found in EnumTemplate.swift // Helper code for WordCount enum is found in EnumTemplate.swift // Helper code for BdkError error is found in ErrorTemplate.swift fileprivate enum FfiConverterOptionUInt8: FfiConverterUsingByteBuffer { typealias SwiftType = UInt8? static func write(_ value: SwiftType, into buf: Writer) { FfiConverterOptional.write(value, into: buf) { item, buf in item.write(into: buf) } } static func read(from buf: Reader) throws -> SwiftType { try FfiConverterOptional.read(from: buf) { buf in try UInt8.read(from: buf) } } } fileprivate enum FfiConverterOptionUInt32: FfiConverterUsingByteBuffer { typealias SwiftType = UInt32? static func write(_ value: SwiftType, into buf: Writer) { FfiConverterOptional.write(value, into: buf) { item, buf in item.write(into: buf) } } static func read(from buf: Reader) throws -> SwiftType { try FfiConverterOptional.read(from: buf) { buf in try UInt32.read(from: buf) } } } fileprivate enum FfiConverterOptionUInt64: FfiConverterUsingByteBuffer { typealias SwiftType = UInt64? static func write(_ value: SwiftType, into buf: Writer) { FfiConverterOptional.write(value, into: buf) { item, buf in item.write(into: buf) } } static func read(from buf: Reader) throws -> SwiftType { try FfiConverterOptional.read(from: buf) { buf in try UInt64.read(from: buf) } } } fileprivate enum FfiConverterOptionFloat: FfiConverterUsingByteBuffer { typealias SwiftType = Float? static func write(_ value: SwiftType, into buf: Writer) { FfiConverterOptional.write(value, into: buf) { item, buf in item.write(into: buf) } } static func read(from buf: Reader) throws -> SwiftType { try FfiConverterOptional.read(from: buf) { buf in try Float.read(from: buf) } } } fileprivate enum FfiConverterOptionString: FfiConverterUsingByteBuffer { typealias SwiftType = String? static func write(_ value: SwiftType, into buf: Writer) { FfiConverterOptional.write(value, into: buf) { item, buf in item.write(into: buf) } } static func read(from buf: Reader) throws -> SwiftType { try FfiConverterOptional.read(from: buf) { buf in try String.read(from: buf) } } } fileprivate enum FfiConverterSequenceEnumTransaction: FfiConverterUsingByteBuffer { typealias SwiftType = [Transaction] static func write(_ value: SwiftType, into buf: Writer) { FfiConverterSequence.write(value, into: buf) { (item, buf) in item.write(into: buf) } } static func read(from buf: Reader) throws -> SwiftType { try FfiConverterSequence.read(from: buf) { buf in try Transaction.read(from: buf) } } } /** * Top level initializers and tear down methods. * * This is generated by uniffi. */ public enum BdkLifecycle { /** * Initialize the FFI and Rust library. This should be only called once per application. */ func initialize() { // No initialization code needed } }