├── .gitignore ├── BdkSwiftSample.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ ├── IDEWorkspaceChecks.plist │ │ └── swiftpm │ │ └── Package.resolved └── xcuserdata │ └── futurepaul.xcuserdatad │ ├── xcdebugger │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ └── xcschememanagement.plist ├── BdkSwiftSample ├── Assets.xcassets │ ├── AccentColor.colorset │ │ └── Contents.json │ ├── AppIcon.appiconset │ │ └── Contents.json │ ├── Background.colorset │ │ └── Contents.json │ ├── Contents.json │ ├── Green.colorset │ │ └── Contents.json │ ├── Primary.colorset │ │ └── Contents.json │ ├── Red.colorset │ │ └── Contents.json │ ├── Shadow.colorset │ │ └── Contents.json │ └── White.colorset │ │ └── Contents.json ├── BdkSwiftSampleApp.swift ├── Components │ ├── BackgroundWrapper.swift │ ├── BalanceDisplay.swift │ ├── BasicButton.swift │ ├── SendReceiveButtons.swift │ └── SingleTxView.swift ├── HomeView.swift ├── MnemonicView.swift ├── Preview Content │ └── Preview Assets.xcassets │ │ └── Contents.json ├── ReceiveView.swift ├── RecoverView.swift ├── SendView.swift ├── SettingsView.swift ├── Styles │ ├── BackButtonMod.swift │ ├── BasicButtonStyle.swift │ ├── BasicTextFieldStyle.swift │ └── BasicTextStyle.swift ├── TxsView.swift ├── WalletView.swift └── WalletViewModel.swift ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | BdkSwiftSample.xcodeproj/xcuserdata/ 2 | BdkSwiftSample.xcodeproj/project.xcworkspace/xcuserdata 3 | -------------------------------------------------------------------------------- /BdkSwiftSample.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 55; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 6EA8DB9B275BD298001B935E /* BdkSwiftSampleApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6EA8DB9A275BD298001B935E /* BdkSwiftSampleApp.swift */; }; 11 | 6EA8DB9D275BD298001B935E /* WalletView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6EA8DB9C275BD298001B935E /* WalletView.swift */; }; 12 | 6EA8DB9F275BD299001B935E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6EA8DB9E275BD299001B935E /* Assets.xcassets */; }; 13 | 6EA8DBA2275BD299001B935E /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6EA8DBA1275BD299001B935E /* Preview Assets.xcassets */; }; 14 | 6EA8DBA9275BD708001B935E /* HomeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6EA8DBA8275BD707001B935E /* HomeView.swift */; }; 15 | 6EA8DBB0275BD72E001B935E /* SendReceiveButtons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6EA8DBAB275BD72E001B935E /* SendReceiveButtons.swift */; }; 16 | 6EA8DBB1275BD72E001B935E /* BasicButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6EA8DBAC275BD72E001B935E /* BasicButton.swift */; }; 17 | 6EA8DBB2275BD72E001B935E /* SingleTxView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6EA8DBAD275BD72E001B935E /* SingleTxView.swift */; }; 18 | 6EA8DBB3275BD72E001B935E /* BackgroundWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6EA8DBAE275BD72E001B935E /* BackgroundWrapper.swift */; }; 19 | 6EA8DBB4275BD72E001B935E /* BalanceDisplay.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6EA8DBAF275BD72E001B935E /* BalanceDisplay.swift */; }; 20 | 6EA8DBBA275BD74C001B935E /* BasicTextFieldStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6EA8DBB6275BD74C001B935E /* BasicTextFieldStyle.swift */; }; 21 | 6EA8DBBB275BD74C001B935E /* BackButtonMod.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6EA8DBB7275BD74C001B935E /* BackButtonMod.swift */; }; 22 | 6EA8DBBC275BD74C001B935E /* BasicTextStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6EA8DBB8275BD74C001B935E /* BasicTextStyle.swift */; }; 23 | 6EA8DBBD275BD74C001B935E /* BasicButtonStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6EA8DBB9275BD74C001B935E /* BasicButtonStyle.swift */; }; 24 | 6EA8DBC4275BD796001B935E /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6EA8DBBE275BD796001B935E /* SettingsView.swift */; }; 25 | 6EA8DBC5275BD796001B935E /* SendView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6EA8DBBF275BD796001B935E /* SendView.swift */; }; 26 | 6EA8DBC6275BD796001B935E /* TxsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6EA8DBC0275BD796001B935E /* TxsView.swift */; }; 27 | 6EA8DBC7275BD796001B935E /* MnemonicView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6EA8DBC1275BD796001B935E /* MnemonicView.swift */; }; 28 | 6EA8DBC8275BD796001B935E /* RecoverView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6EA8DBC2275BD796001B935E /* RecoverView.swift */; }; 29 | 6EA8DBC9275BD796001B935E /* ReceiveView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6EA8DBC3275BD796001B935E /* ReceiveView.swift */; }; 30 | 6EA8DBCB275BD87E001B935E /* WalletViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6EA8DBCA275BD87E001B935E /* WalletViewModel.swift */; }; 31 | AA1684AE28669EF100860C6E /* CodeScanner in Frameworks */ = {isa = PBXBuildFile; productRef = AA1684AD28669EF100860C6E /* CodeScanner */; }; 32 | AAC86C2F2A00492000EBAC79 /* BitcoinDevKit in Frameworks */ = {isa = PBXBuildFile; productRef = AAC86C2E2A00492000EBAC79 /* BitcoinDevKit */; }; 33 | /* End PBXBuildFile section */ 34 | 35 | /* Begin PBXFileReference section */ 36 | 6EA8DB97275BD298001B935E /* BdkSwiftSample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = BdkSwiftSample.app; sourceTree = BUILT_PRODUCTS_DIR; }; 37 | 6EA8DB9A275BD298001B935E /* BdkSwiftSampleApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BdkSwiftSampleApp.swift; sourceTree = ""; }; 38 | 6EA8DB9C275BD298001B935E /* WalletView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WalletView.swift; sourceTree = ""; }; 39 | 6EA8DB9E275BD299001B935E /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 40 | 6EA8DBA1275BD299001B935E /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; 41 | 6EA8DBA8275BD707001B935E /* HomeView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HomeView.swift; sourceTree = ""; }; 42 | 6EA8DBAB275BD72E001B935E /* SendReceiveButtons.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SendReceiveButtons.swift; sourceTree = ""; }; 43 | 6EA8DBAC275BD72E001B935E /* BasicButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BasicButton.swift; sourceTree = ""; }; 44 | 6EA8DBAD275BD72E001B935E /* SingleTxView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SingleTxView.swift; sourceTree = ""; }; 45 | 6EA8DBAE275BD72E001B935E /* BackgroundWrapper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BackgroundWrapper.swift; sourceTree = ""; }; 46 | 6EA8DBAF275BD72E001B935E /* BalanceDisplay.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BalanceDisplay.swift; sourceTree = ""; }; 47 | 6EA8DBB6275BD74C001B935E /* BasicTextFieldStyle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BasicTextFieldStyle.swift; sourceTree = ""; }; 48 | 6EA8DBB7275BD74C001B935E /* BackButtonMod.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BackButtonMod.swift; sourceTree = ""; }; 49 | 6EA8DBB8275BD74C001B935E /* BasicTextStyle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BasicTextStyle.swift; sourceTree = ""; }; 50 | 6EA8DBB9275BD74C001B935E /* BasicButtonStyle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BasicButtonStyle.swift; sourceTree = ""; }; 51 | 6EA8DBBE275BD796001B935E /* SettingsView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = ""; }; 52 | 6EA8DBBF275BD796001B935E /* SendView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SendView.swift; sourceTree = ""; }; 53 | 6EA8DBC0275BD796001B935E /* TxsView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TxsView.swift; sourceTree = ""; }; 54 | 6EA8DBC1275BD796001B935E /* MnemonicView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MnemonicView.swift; sourceTree = ""; }; 55 | 6EA8DBC2275BD796001B935E /* RecoverView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RecoverView.swift; sourceTree = ""; }; 56 | 6EA8DBC3275BD796001B935E /* ReceiveView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReceiveView.swift; sourceTree = ""; }; 57 | 6EA8DBCA275BD87E001B935E /* WalletViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WalletViewModel.swift; sourceTree = ""; }; 58 | AA635F5329CE47E70020D578 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; 59 | /* End PBXFileReference section */ 60 | 61 | /* Begin PBXFrameworksBuildPhase section */ 62 | 6EA8DB94275BD298001B935E /* Frameworks */ = { 63 | isa = PBXFrameworksBuildPhase; 64 | buildActionMask = 2147483647; 65 | files = ( 66 | AAC86C2F2A00492000EBAC79 /* BitcoinDevKit in Frameworks */, 67 | AA1684AE28669EF100860C6E /* CodeScanner in Frameworks */, 68 | ); 69 | runOnlyForDeploymentPostprocessing = 0; 70 | }; 71 | /* End PBXFrameworksBuildPhase section */ 72 | 73 | /* Begin PBXGroup section */ 74 | 6EA8DB8E275BD298001B935E = { 75 | isa = PBXGroup; 76 | children = ( 77 | AACEF60B29A00A7600D6AF44 /* Packages */, 78 | 6EA8DB99275BD298001B935E /* BdkSwiftSample */, 79 | 6EA8DB98275BD298001B935E /* Products */, 80 | AA1684AA28669BA500860C6E /* Frameworks */, 81 | ); 82 | sourceTree = ""; 83 | }; 84 | 6EA8DB98275BD298001B935E /* Products */ = { 85 | isa = PBXGroup; 86 | children = ( 87 | 6EA8DB97275BD298001B935E /* BdkSwiftSample.app */, 88 | ); 89 | name = Products; 90 | sourceTree = ""; 91 | }; 92 | 6EA8DB99275BD298001B935E /* BdkSwiftSample */ = { 93 | isa = PBXGroup; 94 | children = ( 95 | AA635F5329CE47E70020D578 /* Info.plist */, 96 | 6EA8DBB5275BD74C001B935E /* Styles */, 97 | 6EA8DBAA275BD72D001B935E /* Components */, 98 | 6EA8DB9A275BD298001B935E /* BdkSwiftSampleApp.swift */, 99 | 6EA8DB9C275BD298001B935E /* WalletView.swift */, 100 | 6EA8DBA8275BD707001B935E /* HomeView.swift */, 101 | 6EA8DBC1275BD796001B935E /* MnemonicView.swift */, 102 | 6EA8DBCA275BD87E001B935E /* WalletViewModel.swift */, 103 | 6EA8DBC3275BD796001B935E /* ReceiveView.swift */, 104 | 6EA8DBC2275BD796001B935E /* RecoverView.swift */, 105 | 6EA8DBBF275BD796001B935E /* SendView.swift */, 106 | 6EA8DBBE275BD796001B935E /* SettingsView.swift */, 107 | 6EA8DBC0275BD796001B935E /* TxsView.swift */, 108 | 6EA8DB9E275BD299001B935E /* Assets.xcassets */, 109 | 6EA8DBA0275BD299001B935E /* Preview Content */, 110 | ); 111 | path = BdkSwiftSample; 112 | sourceTree = ""; 113 | }; 114 | 6EA8DBA0275BD299001B935E /* Preview Content */ = { 115 | isa = PBXGroup; 116 | children = ( 117 | 6EA8DBA1275BD299001B935E /* Preview Assets.xcassets */, 118 | ); 119 | path = "Preview Content"; 120 | sourceTree = ""; 121 | }; 122 | 6EA8DBAA275BD72D001B935E /* Components */ = { 123 | isa = PBXGroup; 124 | children = ( 125 | 6EA8DBAB275BD72E001B935E /* SendReceiveButtons.swift */, 126 | 6EA8DBAC275BD72E001B935E /* BasicButton.swift */, 127 | 6EA8DBAD275BD72E001B935E /* SingleTxView.swift */, 128 | 6EA8DBAE275BD72E001B935E /* BackgroundWrapper.swift */, 129 | 6EA8DBAF275BD72E001B935E /* BalanceDisplay.swift */, 130 | ); 131 | path = Components; 132 | sourceTree = ""; 133 | }; 134 | 6EA8DBB5275BD74C001B935E /* Styles */ = { 135 | isa = PBXGroup; 136 | children = ( 137 | 6EA8DBB6275BD74C001B935E /* BasicTextFieldStyle.swift */, 138 | 6EA8DBB7275BD74C001B935E /* BackButtonMod.swift */, 139 | 6EA8DBB8275BD74C001B935E /* BasicTextStyle.swift */, 140 | 6EA8DBB9275BD74C001B935E /* BasicButtonStyle.swift */, 141 | ); 142 | path = Styles; 143 | sourceTree = ""; 144 | }; 145 | AA1684AA28669BA500860C6E /* Frameworks */ = { 146 | isa = PBXGroup; 147 | children = ( 148 | ); 149 | name = Frameworks; 150 | sourceTree = ""; 151 | }; 152 | AACEF60B29A00A7600D6AF44 /* Packages */ = { 153 | isa = PBXGroup; 154 | children = ( 155 | ); 156 | name = Packages; 157 | sourceTree = ""; 158 | }; 159 | /* End PBXGroup section */ 160 | 161 | /* Begin PBXNativeTarget section */ 162 | 6EA8DB96275BD298001B935E /* BdkSwiftSample */ = { 163 | isa = PBXNativeTarget; 164 | buildConfigurationList = 6EA8DBA5275BD299001B935E /* Build configuration list for PBXNativeTarget "BdkSwiftSample" */; 165 | buildPhases = ( 166 | 6EA8DB93275BD298001B935E /* Sources */, 167 | 6EA8DB94275BD298001B935E /* Frameworks */, 168 | 6EA8DB95275BD298001B935E /* Resources */, 169 | ); 170 | buildRules = ( 171 | ); 172 | dependencies = ( 173 | ); 174 | name = BdkSwiftSample; 175 | packageProductDependencies = ( 176 | AA1684AD28669EF100860C6E /* CodeScanner */, 177 | AAC86C2E2A00492000EBAC79 /* BitcoinDevKit */, 178 | ); 179 | productName = BdkSwiftSample; 180 | productReference = 6EA8DB97275BD298001B935E /* BdkSwiftSample.app */; 181 | productType = "com.apple.product-type.application"; 182 | }; 183 | /* End PBXNativeTarget section */ 184 | 185 | /* Begin PBXProject section */ 186 | 6EA8DB8F275BD298001B935E /* Project object */ = { 187 | isa = PBXProject; 188 | attributes = { 189 | BuildIndependentTargetsInParallel = 1; 190 | LastSwiftUpdateCheck = 1310; 191 | LastUpgradeCheck = 1310; 192 | TargetAttributes = { 193 | 6EA8DB96275BD298001B935E = { 194 | CreatedOnToolsVersion = 13.1; 195 | }; 196 | }; 197 | }; 198 | buildConfigurationList = 6EA8DB92275BD298001B935E /* Build configuration list for PBXProject "BdkSwiftSample" */; 199 | compatibilityVersion = "Xcode 13.0"; 200 | developmentRegion = en; 201 | hasScannedForEncodings = 0; 202 | knownRegions = ( 203 | en, 204 | Base, 205 | ); 206 | mainGroup = 6EA8DB8E275BD298001B935E; 207 | packageReferences = ( 208 | 6E3A739627643BCE00965365 /* XCRemoteSwiftPackageReference "CodeScanner" */, 209 | AAC86C2D2A00492000EBAC79 /* XCRemoteSwiftPackageReference "bdk-swift" */, 210 | ); 211 | productRefGroup = 6EA8DB98275BD298001B935E /* Products */; 212 | projectDirPath = ""; 213 | projectRoot = ""; 214 | targets = ( 215 | 6EA8DB96275BD298001B935E /* BdkSwiftSample */, 216 | ); 217 | }; 218 | /* End PBXProject section */ 219 | 220 | /* Begin PBXResourcesBuildPhase section */ 221 | 6EA8DB95275BD298001B935E /* Resources */ = { 222 | isa = PBXResourcesBuildPhase; 223 | buildActionMask = 2147483647; 224 | files = ( 225 | 6EA8DBA2275BD299001B935E /* Preview Assets.xcassets in Resources */, 226 | 6EA8DB9F275BD299001B935E /* Assets.xcassets in Resources */, 227 | ); 228 | runOnlyForDeploymentPostprocessing = 0; 229 | }; 230 | /* End PBXResourcesBuildPhase section */ 231 | 232 | /* Begin PBXSourcesBuildPhase section */ 233 | 6EA8DB93275BD298001B935E /* Sources */ = { 234 | isa = PBXSourcesBuildPhase; 235 | buildActionMask = 2147483647; 236 | files = ( 237 | 6EA8DBC6275BD796001B935E /* TxsView.swift in Sources */, 238 | 6EA8DBBD275BD74C001B935E /* BasicButtonStyle.swift in Sources */, 239 | 6EA8DBCB275BD87E001B935E /* WalletViewModel.swift in Sources */, 240 | 6EA8DBA9275BD708001B935E /* HomeView.swift in Sources */, 241 | 6EA8DBBB275BD74C001B935E /* BackButtonMod.swift in Sources */, 242 | 6EA8DBC8275BD796001B935E /* RecoverView.swift in Sources */, 243 | 6EA8DBB1275BD72E001B935E /* BasicButton.swift in Sources */, 244 | 6EA8DBC9275BD796001B935E /* ReceiveView.swift in Sources */, 245 | 6EA8DBB3275BD72E001B935E /* BackgroundWrapper.swift in Sources */, 246 | 6EA8DBB4275BD72E001B935E /* BalanceDisplay.swift in Sources */, 247 | 6EA8DBBA275BD74C001B935E /* BasicTextFieldStyle.swift in Sources */, 248 | 6EA8DB9D275BD298001B935E /* WalletView.swift in Sources */, 249 | 6EA8DB9B275BD298001B935E /* BdkSwiftSampleApp.swift in Sources */, 250 | 6EA8DBB2275BD72E001B935E /* SingleTxView.swift in Sources */, 251 | 6EA8DBB0275BD72E001B935E /* SendReceiveButtons.swift in Sources */, 252 | 6EA8DBBC275BD74C001B935E /* BasicTextStyle.swift in Sources */, 253 | 6EA8DBC5275BD796001B935E /* SendView.swift in Sources */, 254 | 6EA8DBC7275BD796001B935E /* MnemonicView.swift in Sources */, 255 | 6EA8DBC4275BD796001B935E /* SettingsView.swift in Sources */, 256 | ); 257 | runOnlyForDeploymentPostprocessing = 0; 258 | }; 259 | /* End PBXSourcesBuildPhase section */ 260 | 261 | /* Begin XCBuildConfiguration section */ 262 | 6EA8DBA3275BD299001B935E /* Debug */ = { 263 | isa = XCBuildConfiguration; 264 | buildSettings = { 265 | ALWAYS_SEARCH_USER_PATHS = NO; 266 | CLANG_ANALYZER_NONNULL = YES; 267 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 268 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; 269 | CLANG_CXX_LIBRARY = "libc++"; 270 | CLANG_ENABLE_MODULES = YES; 271 | CLANG_ENABLE_OBJC_ARC = YES; 272 | CLANG_ENABLE_OBJC_WEAK = YES; 273 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 274 | CLANG_WARN_BOOL_CONVERSION = YES; 275 | CLANG_WARN_COMMA = YES; 276 | CLANG_WARN_CONSTANT_CONVERSION = YES; 277 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 278 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 279 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 280 | CLANG_WARN_EMPTY_BODY = YES; 281 | CLANG_WARN_ENUM_CONVERSION = YES; 282 | CLANG_WARN_INFINITE_RECURSION = YES; 283 | CLANG_WARN_INT_CONVERSION = YES; 284 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 285 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 286 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 287 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 288 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 289 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 290 | CLANG_WARN_STRICT_PROTOTYPES = YES; 291 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 292 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 293 | CLANG_WARN_UNREACHABLE_CODE = YES; 294 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 295 | COPY_PHASE_STRIP = NO; 296 | DEBUG_INFORMATION_FORMAT = dwarf; 297 | ENABLE_STRICT_OBJC_MSGSEND = YES; 298 | ENABLE_TESTABILITY = YES; 299 | GCC_C_LANGUAGE_STANDARD = gnu11; 300 | GCC_DYNAMIC_NO_PIC = NO; 301 | GCC_NO_COMMON_BLOCKS = YES; 302 | GCC_OPTIMIZATION_LEVEL = 0; 303 | GCC_PREPROCESSOR_DEFINITIONS = ( 304 | "DEBUG=1", 305 | "$(inherited)", 306 | ); 307 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 308 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 309 | GCC_WARN_UNDECLARED_SELECTOR = YES; 310 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 311 | GCC_WARN_UNUSED_FUNCTION = YES; 312 | GCC_WARN_UNUSED_VARIABLE = YES; 313 | IPHONEOS_DEPLOYMENT_TARGET = 15.0; 314 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 315 | MTL_FAST_MATH = YES; 316 | ONLY_ACTIVE_ARCH = YES; 317 | SDKROOT = iphoneos; 318 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 319 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 320 | }; 321 | name = Debug; 322 | }; 323 | 6EA8DBA4275BD299001B935E /* Release */ = { 324 | isa = XCBuildConfiguration; 325 | buildSettings = { 326 | ALWAYS_SEARCH_USER_PATHS = NO; 327 | CLANG_ANALYZER_NONNULL = YES; 328 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 329 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; 330 | CLANG_CXX_LIBRARY = "libc++"; 331 | CLANG_ENABLE_MODULES = YES; 332 | CLANG_ENABLE_OBJC_ARC = YES; 333 | CLANG_ENABLE_OBJC_WEAK = YES; 334 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 335 | CLANG_WARN_BOOL_CONVERSION = YES; 336 | CLANG_WARN_COMMA = YES; 337 | CLANG_WARN_CONSTANT_CONVERSION = YES; 338 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 339 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 340 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 341 | CLANG_WARN_EMPTY_BODY = YES; 342 | CLANG_WARN_ENUM_CONVERSION = YES; 343 | CLANG_WARN_INFINITE_RECURSION = YES; 344 | CLANG_WARN_INT_CONVERSION = YES; 345 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 346 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 347 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 348 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 349 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 350 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 351 | CLANG_WARN_STRICT_PROTOTYPES = YES; 352 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 353 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 354 | CLANG_WARN_UNREACHABLE_CODE = YES; 355 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 356 | COPY_PHASE_STRIP = NO; 357 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 358 | ENABLE_NS_ASSERTIONS = NO; 359 | ENABLE_STRICT_OBJC_MSGSEND = YES; 360 | GCC_C_LANGUAGE_STANDARD = gnu11; 361 | GCC_NO_COMMON_BLOCKS = YES; 362 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 363 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 364 | GCC_WARN_UNDECLARED_SELECTOR = YES; 365 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 366 | GCC_WARN_UNUSED_FUNCTION = YES; 367 | GCC_WARN_UNUSED_VARIABLE = YES; 368 | IPHONEOS_DEPLOYMENT_TARGET = 15.0; 369 | MTL_ENABLE_DEBUG_INFO = NO; 370 | MTL_FAST_MATH = YES; 371 | SDKROOT = iphoneos; 372 | SWIFT_COMPILATION_MODE = wholemodule; 373 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 374 | VALIDATE_PRODUCT = YES; 375 | }; 376 | name = Release; 377 | }; 378 | 6EA8DBA6275BD299001B935E /* Debug */ = { 379 | isa = XCBuildConfiguration; 380 | buildSettings = { 381 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 382 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 383 | CODE_SIGN_STYLE = Automatic; 384 | CURRENT_PROJECT_VERSION = 1; 385 | DEVELOPMENT_ASSET_PATHS = "BdkSwiftSample/Preview\\ Content"; 386 | DEVELOPMENT_TEAM = JBLHZ83X6T; 387 | ENABLE_PREVIEWS = YES; 388 | GENERATE_INFOPLIST_FILE = YES; 389 | INFOPLIST_KEY_NSCameraUsageDescription = "Scan Bitcoin addresses for sending"; 390 | INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; 391 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; 392 | INFOPLIST_KEY_UILaunchScreen_Generation = YES; 393 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 394 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 395 | LD_RUNPATH_SEARCH_PATHS = ( 396 | "$(inherited)", 397 | "@executable_path/Frameworks", 398 | ); 399 | MARKETING_VERSION = 1.0; 400 | PRODUCT_BUNDLE_IDENTIFIER = lol.paul.BdkSwiftSample; 401 | PRODUCT_NAME = "$(TARGET_NAME)"; 402 | SWIFT_EMIT_LOC_STRINGS = YES; 403 | SWIFT_VERSION = 5.0; 404 | TARGETED_DEVICE_FAMILY = "1,2"; 405 | }; 406 | name = Debug; 407 | }; 408 | 6EA8DBA7275BD299001B935E /* Release */ = { 409 | isa = XCBuildConfiguration; 410 | buildSettings = { 411 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 412 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 413 | CODE_SIGN_STYLE = Automatic; 414 | CURRENT_PROJECT_VERSION = 1; 415 | DEVELOPMENT_ASSET_PATHS = "BdkSwiftSample/Preview\\ Content"; 416 | DEVELOPMENT_TEAM = JBLHZ83X6T; 417 | ENABLE_PREVIEWS = YES; 418 | GENERATE_INFOPLIST_FILE = YES; 419 | INFOPLIST_KEY_NSCameraUsageDescription = "Scan Bitcoin addresses for sending"; 420 | INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; 421 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; 422 | INFOPLIST_KEY_UILaunchScreen_Generation = YES; 423 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 424 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 425 | LD_RUNPATH_SEARCH_PATHS = ( 426 | "$(inherited)", 427 | "@executable_path/Frameworks", 428 | ); 429 | MARKETING_VERSION = 1.0; 430 | PRODUCT_BUNDLE_IDENTIFIER = lol.paul.BdkSwiftSample; 431 | PRODUCT_NAME = "$(TARGET_NAME)"; 432 | SWIFT_EMIT_LOC_STRINGS = YES; 433 | SWIFT_VERSION = 5.0; 434 | TARGETED_DEVICE_FAMILY = "1,2"; 435 | }; 436 | name = Release; 437 | }; 438 | /* End XCBuildConfiguration section */ 439 | 440 | /* Begin XCConfigurationList section */ 441 | 6EA8DB92275BD298001B935E /* Build configuration list for PBXProject "BdkSwiftSample" */ = { 442 | isa = XCConfigurationList; 443 | buildConfigurations = ( 444 | 6EA8DBA3275BD299001B935E /* Debug */, 445 | 6EA8DBA4275BD299001B935E /* Release */, 446 | ); 447 | defaultConfigurationIsVisible = 0; 448 | defaultConfigurationName = Release; 449 | }; 450 | 6EA8DBA5275BD299001B935E /* Build configuration list for PBXNativeTarget "BdkSwiftSample" */ = { 451 | isa = XCConfigurationList; 452 | buildConfigurations = ( 453 | 6EA8DBA6275BD299001B935E /* Debug */, 454 | 6EA8DBA7275BD299001B935E /* Release */, 455 | ); 456 | defaultConfigurationIsVisible = 0; 457 | defaultConfigurationName = Release; 458 | }; 459 | /* End XCConfigurationList section */ 460 | 461 | /* Begin XCRemoteSwiftPackageReference section */ 462 | 6E3A739627643BCE00965365 /* XCRemoteSwiftPackageReference "CodeScanner" */ = { 463 | isa = XCRemoteSwiftPackageReference; 464 | repositoryURL = "https://github.com/twostraws/CodeScanner"; 465 | requirement = { 466 | kind = exactVersion; 467 | version = 1.1.0; 468 | }; 469 | }; 470 | AAC86C2D2A00492000EBAC79 /* XCRemoteSwiftPackageReference "bdk-swift" */ = { 471 | isa = XCRemoteSwiftPackageReference; 472 | repositoryURL = "https://github.com/bitcoindevkit/bdk-swift.git"; 473 | requirement = { 474 | kind = upToNextMajorVersion; 475 | minimumVersion = 0.28.0; 476 | }; 477 | }; 478 | /* End XCRemoteSwiftPackageReference section */ 479 | 480 | /* Begin XCSwiftPackageProductDependency section */ 481 | AA1684AD28669EF100860C6E /* CodeScanner */ = { 482 | isa = XCSwiftPackageProductDependency; 483 | package = 6E3A739627643BCE00965365 /* XCRemoteSwiftPackageReference "CodeScanner" */; 484 | productName = CodeScanner; 485 | }; 486 | AAC86C2E2A00492000EBAC79 /* BitcoinDevKit */ = { 487 | isa = XCSwiftPackageProductDependency; 488 | package = AAC86C2D2A00492000EBAC79 /* XCRemoteSwiftPackageReference "bdk-swift" */; 489 | productName = BitcoinDevKit; 490 | }; 491 | /* End XCSwiftPackageProductDependency section */ 492 | }; 493 | rootObject = 6EA8DB8F275BD298001B935E /* Project object */; 494 | } 495 | -------------------------------------------------------------------------------- /BdkSwiftSample.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /BdkSwiftSample.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /BdkSwiftSample.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved: -------------------------------------------------------------------------------- 1 | { 2 | "pins" : [ 3 | { 4 | "identity" : "bdk-swift", 5 | "kind" : "remoteSourceControl", 6 | "location" : "https://github.com/bitcoindevkit/bdk-swift.git", 7 | "state" : { 8 | "revision" : "eea9701182b656966add1868fa29c366421a6239", 9 | "version" : "0.28.0" 10 | } 11 | }, 12 | { 13 | "identity" : "codescanner", 14 | "kind" : "remoteSourceControl", 15 | "location" : "https://github.com/twostraws/CodeScanner", 16 | "state" : { 17 | "revision" : "8a9ce909a4ea502d4a2ccf327ae8c16b7e48e740", 18 | "version" : "1.1.0" 19 | } 20 | } 21 | ], 22 | "version" : 2 23 | } 24 | -------------------------------------------------------------------------------- /BdkSwiftSample.xcodeproj/xcuserdata/futurepaul.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | -------------------------------------------------------------------------------- /BdkSwiftSample.xcodeproj/xcuserdata/futurepaul.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | BdkSwiftSample.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /BdkSwiftSample/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /BdkSwiftSample/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "scale" : "2x", 6 | "size" : "20x20" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "scale" : "3x", 11 | "size" : "20x20" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "scale" : "2x", 16 | "size" : "29x29" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "scale" : "3x", 21 | "size" : "29x29" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "scale" : "2x", 26 | "size" : "40x40" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "scale" : "3x", 31 | "size" : "40x40" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "scale" : "2x", 36 | "size" : "60x60" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "scale" : "3x", 41 | "size" : "60x60" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "scale" : "1x", 46 | "size" : "20x20" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "scale" : "2x", 51 | "size" : "20x20" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "scale" : "1x", 56 | "size" : "29x29" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "scale" : "2x", 61 | "size" : "29x29" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "scale" : "1x", 66 | "size" : "40x40" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "scale" : "2x", 71 | "size" : "40x40" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "scale" : "1x", 76 | "size" : "76x76" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "scale" : "2x", 81 | "size" : "76x76" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "scale" : "2x", 86 | "size" : "83.5x83.5" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "scale" : "1x", 91 | "size" : "1024x1024" 92 | } 93 | ], 94 | "info" : { 95 | "author" : "xcode", 96 | "version" : 1 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /BdkSwiftSample/Assets.xcassets/Background.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "color-space" : "display-p3", 6 | "components" : { 7 | "alpha" : "1.000", 8 | "blue" : "0.184", 9 | "green" : "0.165", 10 | "red" : "0.161" 11 | } 12 | }, 13 | "idiom" : "universal" 14 | }, 15 | { 16 | "appearances" : [ 17 | { 18 | "appearance" : "luminosity", 19 | "value" : "dark" 20 | } 21 | ], 22 | "color" : { 23 | "color-space" : "display-p3", 24 | "components" : { 25 | "alpha" : "1.000", 26 | "blue" : "0.184", 27 | "green" : "0.165", 28 | "red" : "0.161" 29 | } 30 | }, 31 | "idiom" : "universal" 32 | } 33 | ], 34 | "info" : { 35 | "author" : "xcode", 36 | "version" : 1 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /BdkSwiftSample/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /BdkSwiftSample/Assets.xcassets/Green.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "color-space" : "display-p3", 6 | "components" : { 7 | "alpha" : "1.000", 8 | "blue" : "0.925", 9 | "green" : "0.973", 10 | "red" : "0.757" 11 | } 12 | }, 13 | "idiom" : "universal" 14 | }, 15 | { 16 | "appearances" : [ 17 | { 18 | "appearance" : "luminosity", 19 | "value" : "dark" 20 | } 21 | ], 22 | "color" : { 23 | "color-space" : "display-p3", 24 | "components" : { 25 | "alpha" : "1.000", 26 | "blue" : "0.925", 27 | "green" : "0.973", 28 | "red" : "0.757" 29 | } 30 | }, 31 | "idiom" : "universal" 32 | } 33 | ], 34 | "info" : { 35 | "author" : "xcode", 36 | "version" : 1 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /BdkSwiftSample/Assets.xcassets/Primary.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "color-space" : "display-p3", 6 | "components" : { 7 | "alpha" : "1.000", 8 | "blue" : "0.992", 9 | "green" : "0.871", 10 | "red" : "0.541" 11 | } 12 | }, 13 | "idiom" : "universal" 14 | }, 15 | { 16 | "appearances" : [ 17 | { 18 | "appearance" : "luminosity", 19 | "value" : "dark" 20 | } 21 | ], 22 | "color" : { 23 | "color-space" : "display-p3", 24 | "components" : { 25 | "alpha" : "1.000", 26 | "blue" : "0.992", 27 | "green" : "0.871", 28 | "red" : "0.541" 29 | } 30 | }, 31 | "idiom" : "universal" 32 | } 33 | ], 34 | "info" : { 35 | "author" : "xcode", 36 | "version" : 1 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /BdkSwiftSample/Assets.xcassets/Red.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "color-space" : "display-p3", 6 | "components" : { 7 | "alpha" : "1.000", 8 | "blue" : "0.478", 9 | "green" : "0.553", 10 | "red" : "0.976" 11 | } 12 | }, 13 | "idiom" : "universal" 14 | }, 15 | { 16 | "appearances" : [ 17 | { 18 | "appearance" : "luminosity", 19 | "value" : "dark" 20 | } 21 | ], 22 | "color" : { 23 | "color-space" : "display-p3", 24 | "components" : { 25 | "alpha" : "1.000", 26 | "blue" : "0.478", 27 | "green" : "0.553", 28 | "red" : "0.976" 29 | } 30 | }, 31 | "idiom" : "universal" 32 | } 33 | ], 34 | "info" : { 35 | "author" : "xcode", 36 | "version" : 1 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /BdkSwiftSample/Assets.xcassets/Shadow.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "color-space" : "display-p3", 6 | "components" : { 7 | "alpha" : "1.000", 8 | "blue" : "0.122", 9 | "green" : "0.108", 10 | "red" : "0.106" 11 | } 12 | }, 13 | "idiom" : "universal" 14 | }, 15 | { 16 | "appearances" : [ 17 | { 18 | "appearance" : "luminosity", 19 | "value" : "dark" 20 | } 21 | ], 22 | "color" : { 23 | "color-space" : "display-p3", 24 | "components" : { 25 | "alpha" : "1.000", 26 | "blue" : "0.122", 27 | "green" : "0.108", 28 | "red" : "0.106" 29 | } 30 | }, 31 | "idiom" : "universal" 32 | } 33 | ], 34 | "info" : { 35 | "author" : "xcode", 36 | "version" : 1 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /BdkSwiftSample/Assets.xcassets/White.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "color-space" : "display-p3", 6 | "components" : { 7 | "alpha" : "1.000", 8 | "blue" : "0.941", 9 | "green" : "0.922", 10 | "red" : "0.910" 11 | } 12 | }, 13 | "idiom" : "universal" 14 | }, 15 | { 16 | "appearances" : [ 17 | { 18 | "appearance" : "luminosity", 19 | "value" : "dark" 20 | } 21 | ], 22 | "color" : { 23 | "color-space" : "display-p3", 24 | "components" : { 25 | "alpha" : "1.000", 26 | "blue" : "0.941", 27 | "green" : "0.922", 28 | "red" : "0.910" 29 | } 30 | }, 31 | "idiom" : "universal" 32 | } 33 | ], 34 | "info" : { 35 | "author" : "xcode", 36 | "version" : 1 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /BdkSwiftSample/BdkSwiftSampleApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BdkSwiftSampleApp.swift 3 | // BdkSwiftSample 4 | // 5 | // Created by Paul Miller on 12/4/21. 6 | // 7 | 8 | import SwiftUI 9 | 10 | @main 11 | struct BdkSwiftSampleApp: App { 12 | @StateObject var wallet = WalletViewModel(); 13 | var body: some Scene { 14 | WindowGroup { 15 | WalletView().environmentObject(wallet).preferredColorScheme(.dark) 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /BdkSwiftSample/Components/BackgroundWrapper.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BackgroundWrapper.swift 3 | // MyFirstApp 4 | // 5 | // Created by Paul Miller on 11/5/21. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct BackgroundWrapper: View { 11 | // @Environment(\.presentationMode) var presentation 12 | let content: Content 13 | 14 | init(@ViewBuilder content: () -> Content) { 15 | self.content = content() 16 | } 17 | 18 | var body: some View { 19 | ZStack { 20 | Color("Background").ignoresSafeArea() 21 | VStack { 22 | content 23 | 24 | }.padding(10) 25 | } 26 | // .navigationBarBackButtonHidden(true) 27 | // .toolbar(content: { 28 | // ToolbarItem (placement: .navigation) { 29 | // Image(systemName: "arrow.left") 30 | // .foregroundColor(.white) 31 | // .onTapGesture { 32 | // // code to dismiss the view 33 | // self.presentation.wrappedValue.dismiss() 34 | // } 35 | // } 36 | // }) 37 | } 38 | 39 | } 40 | 41 | struct BackgroundWrapper_Previews: PreviewProvider { 42 | static var previews: some View { 43 | BackgroundWrapper() { 44 | Text("Testing") 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /BdkSwiftSample/Components/BalanceDisplay.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BalanceDisplay.swift 3 | // MyFirstApp 4 | // 5 | // Created by Paul Miller on 11/4/21. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct BalanceDisplay: View { 11 | var balance: String 12 | 13 | var body: some View { 14 | Text("₿ \(balance)") 15 | .font(.system(size: 32, design: .monospaced)) 16 | .fontWeight(.semibold) 17 | .foregroundColor(Color.white) 18 | .padding(10) 19 | .frame(maxWidth: .infinity) 20 | .background(Color("Shadow")) 21 | } 22 | } 23 | 24 | struct BalanceDisplay_Previews: PreviewProvider { 25 | static var previews: some View { 26 | BalanceDisplay(balance: "0.00042069") 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /BdkSwiftSample/Components/BasicButton.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BasicButton.swift 3 | // MyFirstApp 4 | // 5 | // Created by Paul Miller on 11/4/21. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct BasicButton: View { 11 | var action: () -> Void 12 | var text: String 13 | var color = "Primary" 14 | 15 | var body: some View { 16 | Button(action: action) { 17 | Text(text) 18 | .font(.system(size: 14, design: .monospaced)) 19 | .fontWeight(.bold) 20 | .frame(maxWidth: .infinity, maxHeight: 40) 21 | .foregroundColor(Color("Shadow")) 22 | .padding(10) 23 | .background(Color(color)) 24 | .cornerRadius(10.0) 25 | .shadow(color: Color("Shadow"), radius: 1, x: 5, y: 5) 26 | } 27 | } 28 | } 29 | 30 | struct BasicButton_Previews: PreviewProvider { 31 | static var previews: some View { 32 | BasicButton(action: {}, text: "Test") 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /BdkSwiftSample/Components/SendReceiveButtons.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SendReceiveButtons.swift 3 | // MyFirstApp 4 | // 5 | // Created by Paul Miller on 11/5/21. 6 | // 7 | 8 | import SwiftUI 9 | import BitcoinDevKit 10 | 11 | struct SendReceiveButtons: View { 12 | var wallet: Wallet 13 | var blockchain: Blockchain 14 | 15 | func getWidth(w: CGFloat) -> CGFloat { 16 | return (w - 10.0) / 2.0 17 | } 18 | 19 | 20 | @State private var goToSend = false 21 | @State private var goToReceive = false 22 | 23 | var body: some View { 24 | // Invisible link to receive 25 | NavigationLink(destination: ReceiveView(), isActive: $goToReceive) { EmptyView() } 26 | 27 | // Invisible link to Send 28 | NavigationLink(destination: SendView(onSend: { recipient, amount in 29 | do { 30 | let address = try Address(address: recipient) 31 | let script = address.scriptPubkey() 32 | let txBuilder = TxBuilder().addRecipient(script: script, amount: amount) 33 | let details = try txBuilder.finish(wallet: wallet) 34 | let _ = try wallet.sign(psbt: details.psbt, signOptions: nil) 35 | let tx = details.psbt.extractTx() 36 | try blockchain.broadcast(transaction: tx) 37 | let txid = details.psbt.txid() 38 | print(txid) 39 | } catch let error { 40 | print(error) 41 | } 42 | }), isActive: $goToSend) { EmptyView() } 43 | GeometryReader { geometry in 44 | HStack(spacing: 10) { 45 | let w = getWidth(w: geometry.size.width) 46 | Button(action: { goToReceive = true }) { 47 | Text("receive") 48 | .font(.system(size: 14, design: .monospaced)) 49 | .fontWeight(.bold) 50 | .foregroundColor(Color("Shadow")) 51 | .frame(width: w, height: w) 52 | .background(Color("Green")) 53 | .cornerRadius(10.0) 54 | .shadow(color: Color("Shadow"), radius: 1, x: 5, y: 5) 55 | } 56 | Button(action: { goToSend = true }) { 57 | Text("send") 58 | .font(.system(size: 14, design: .monospaced)) 59 | .fontWeight(.bold) 60 | .foregroundColor(Color("Shadow")) 61 | .frame(width: w, height: w) 62 | .background(Color("Red")) 63 | .cornerRadius(10.0) 64 | .shadow(color: Color("Shadow"), radius: 1, x: 5, y: 5) 65 | } 66 | } 67 | } 68 | } 69 | } 70 | 71 | struct SendReceiveButtons_Previews: PreviewProvider { 72 | static var previews: some View { 73 | // SendReceiveButtons() 74 | Text("Hello") 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /BdkSwiftSample/Components/SingleTxView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SingleTxView.swift 3 | // MyFirstApp 4 | // 5 | // Created by Paul Miller on 11/5/21. 6 | // 7 | 8 | import SwiftUI 9 | import BitcoinDevKit 10 | 11 | struct SingleTxView: View { 12 | var transactionDetails: TransactionDetails 13 | 14 | var body: some View { 15 | VStack(alignment: .leading, spacing: 5) { 16 | if transactionDetails.confirmationTime == nil { 17 | HStack { 18 | Text("Received:").textStyle(BasicTextStyle(white: true, bold: true)) 19 | Text(String(transactionDetails.received)).textStyle(BasicTextStyle(white: true)) 20 | } 21 | HStack { 22 | Text("Sent:").textStyle(BasicTextStyle(white: true, bold: true)) 23 | Text(String(transactionDetails.sent)).textStyle(BasicTextStyle(white: true)) 24 | } 25 | HStack { 26 | Text("Fees:").textStyle(BasicTextStyle(white: true, bold: true)) 27 | Text(String(transactionDetails.fee ?? 0)).textStyle(BasicTextStyle(white: true)) 28 | } 29 | HStack { 30 | Text("Txid:").textStyle(BasicTextStyle(white: true, bold: true)) 31 | Text(transactionDetails.txid).textStyle(BasicTextStyle(white: true)) 32 | } 33 | } else { 34 | HStack { 35 | Text("Confirmed:").textStyle(BasicTextStyle(white: true, bold: true)) 36 | Text((Date(timeIntervalSince1970: TimeInterval(transactionDetails.confirmationTime!.timestamp)).getFormattedDate(format: "yyyy-MM-dd HH:mm:ss"))).textStyle(BasicTextStyle(white: true)) 37 | } 38 | HStack { 39 | Text("Block:").textStyle(BasicTextStyle(white: true, bold: true)) 40 | Text(String(transactionDetails.confirmationTime!.height)).textStyle(BasicTextStyle(white: true)) 41 | } 42 | HStack { 43 | Text("Received:").textStyle(BasicTextStyle(white: true, bold: true)) 44 | Text(String(transactionDetails.received)).textStyle(BasicTextStyle(white: true)) 45 | } 46 | HStack { 47 | Text("Sent:").textStyle(BasicTextStyle(white: true, bold: true)) 48 | Text(String(transactionDetails.sent)).textStyle(BasicTextStyle(white: true)) 49 | } 50 | HStack { 51 | Text("Fees:").textStyle(BasicTextStyle(white: true, bold: true)) 52 | Text(String(transactionDetails.fee ?? 0)).textStyle(BasicTextStyle(white: true)) 53 | } 54 | HStack { 55 | Text("Txid:").textStyle(BasicTextStyle(white: true, bold: true)) 56 | Text(transactionDetails.txid).textStyle(BasicTextStyle(white: true)) 57 | } 58 | } 59 | }.padding(10) 60 | .background(Color("Shadow")).cornerRadius(5) 61 | .contextMenu { 62 | Button(action: { 63 | UIPasteboard.general.string = transactionDetails.txid}) { 64 | Text("Copy TXID") 65 | } 66 | } 67 | .padding(.vertical, 10) 68 | } 69 | } 70 | 71 | struct SingleTxView_Previews: PreviewProvider { 72 | static var previews: some View { 73 | SingleTxView(transactionDetails: TransactionDetails(transaction: nil, fee: 250, received: 1000, sent: 10000, txid: "some-other-tx-id", confirmationTime: BlockTime(height: 20087, timestamp: 1635863544))) 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /BdkSwiftSample/HomeView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HomeView.swift 3 | // MyFirstApp 4 | // 5 | // Created by Paul Miller on 11/4/21. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct HomeView: View { 11 | @EnvironmentObject var viewModel: WalletViewModel 12 | 13 | @State private var goToIntro = false 14 | @State private var goToTxs = false 15 | 16 | var body: some View { 17 | BackgroundWrapper { 18 | VStack { 19 | Button(action: {() in goToIntro = true}) { 20 | HStack() { 21 | Spacer() 22 | Image(systemName: "gearshape.fill") 23 | .font(.system(size: 20, weight: .light)) 24 | .foregroundColor(Color.white) 25 | } 26 | } 27 | NavigationLink(destination: SettingsView(), isActive: $goToIntro) { EmptyView() } 28 | } 29 | Spacer().frame(minHeight: 40) 30 | BalanceDisplay(balance: viewModel.balanceText ).padding(.leading, -10).padding(.trailing, -10) 31 | Spacer().frame(minHeight: 40) 32 | VStack() { 33 | BasicButton(action: viewModel.sync, text: "sync wallet").padding(.bottom, 10) 34 | NavigationLink(destination: TxsView(), isActive: $goToTxs) { EmptyView() } 35 | BasicButton(action: { goToTxs = true}, text: "transaction history") 36 | }.padding(.bottom, 10) 37 | switch viewModel.state { 38 | case .loaded(let wallet, let blockchain): 39 | do { 40 | SendReceiveButtons(wallet: wallet, blockchain: blockchain) 41 | } 42 | default: do { } 43 | } 44 | Spacer().frame(minHeight: 40) 45 | }.navigationBarBackButtonHidden(true) 46 | .navigationBarHidden(true) 47 | } 48 | } 49 | 50 | struct HomeView_Previews: PreviewProvider { 51 | static var previews: some View { 52 | HomeView() 53 | .environmentObject(WalletViewModel()) 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /BdkSwiftSample/MnemonicView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // IntroView.swift 3 | // MyFirstApp 4 | // 5 | // Created by Paul Miller on 11/4/21. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct MnemonicView: View { 11 | var words: String 12 | @State private var goHome = false 13 | 14 | var body: some View { 15 | BackgroundWrapper { 16 | Spacer() 17 | Text(words).textStyle(BasicTextStyle(big: true, white: true)).contextMenu { 18 | Button(action: { 19 | UIPasteboard.general.string = self.words}) { 20 | Text("Copy to clipboard") 21 | } 22 | } 23 | Spacer() 24 | NavigationLink(destination: WalletView(), isActive: $goHome) { EmptyView() } 25 | BasicButton(action: { () in goHome = true}, text: "Back to Wallet") 26 | } 27 | .navigationTitle("Mnemonic") 28 | .modifier(BackButtonMod()) 29 | } 30 | } 31 | 32 | struct RecoveryView_Previews: PreviewProvider { 33 | static var previews: some View { 34 | MnemonicView(words: "clutch solar sand travel vital fitness hand piece dial flag garment grant") 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /BdkSwiftSample/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /BdkSwiftSample/ReceiveView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ReceiveView.swift 3 | // MyFirstApp 4 | // 5 | // Created by Paul Miller on 11/5/21. 6 | // 7 | 8 | import SwiftUI 9 | import CoreImage.CIFilterBuiltins 10 | import BitcoinDevKit 11 | 12 | let context = CIContext() 13 | let filter = CIFilter.qrCodeGenerator() 14 | 15 | struct ReceiveView: View { 16 | @EnvironmentObject var viewModel: WalletViewModel 17 | @State private var address: String = "tb1qfafsasdfasd" 18 | 19 | func splitAddress(address: String) -> (String, String) { 20 | let length = address.count 21 | 22 | return (String(address.prefix(length / 2)), String(address.suffix(length / 2))) 23 | } 24 | 25 | func getAddress() { 26 | switch viewModel.state { 27 | case .loaded(let wallet, _): 28 | do { 29 | let addressInfo = try wallet.getAddress(addressIndex: AddressIndex.new) 30 | address = addressInfo.address.asString() 31 | } catch { 32 | address = "ERROR" 33 | } 34 | default: do { } 35 | } 36 | } 37 | 38 | func generateQRCode(from string: String) -> UIImage { 39 | let data = Data(string.utf8) 40 | filter.setValue(data, forKey: "inputMessage") 41 | 42 | if let outputImage = filter.outputImage { 43 | if let cgimg = context.createCGImage(outputImage, from: outputImage.extent) { 44 | return UIImage(cgImage: cgimg) 45 | } 46 | } 47 | 48 | return UIImage(systemName: "xmark.circle") ?? UIImage() 49 | } 50 | 51 | var body: some View { 52 | BackgroundWrapper { 53 | Spacer() 54 | VStack { 55 | Image(uiImage: generateQRCode(from: "bitcoin:\(address)")) 56 | .interpolation(.none) 57 | .resizable() 58 | .scaledToFit() 59 | .frame(width: 200, height: 200) 60 | Spacer() 61 | Text(splitAddress(address: address).0).textStyle(BasicTextStyle(white: true)) 62 | Text(splitAddress(address: address).1).textStyle(BasicTextStyle(white: true)) 63 | .onTapGesture(count: 1) { 64 | UIPasteboard.general.string = address 65 | } 66 | Spacer() 67 | }.contextMenu { 68 | Button(action: { 69 | UIPasteboard.general.string = address}) { 70 | Text("Copy to clipboard") 71 | } 72 | } 73 | Spacer() 74 | BasicButton(action: getAddress, text: "Generate new address", color: "Green") 75 | } 76 | .navigationTitle("Receive Address") 77 | .modifier(BackButtonMod()) 78 | .onAppear(perform: getAddress) 79 | } 80 | } 81 | 82 | struct ReceiveView_Previews: PreviewProvider { 83 | static var previews: some View { 84 | ReceiveView() 85 | .environmentObject(WalletViewModel()) 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /BdkSwiftSample/RecoverView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // RecoverView.swift 3 | // MyFirstApp 4 | // 5 | // Created by Paul Miller on 11/5/21. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct RecoverView: View { 11 | @State private var words = Array(repeating: "", count: 12) 12 | 13 | var body: some View { 14 | BackgroundWrapper { 15 | ScrollView { 16 | ForEach(0..<12) { i in 17 | TextField( 18 | "Word \(i + 1)", 19 | text: $words[i] 20 | ) 21 | } 22 | .disableAutocorrection(true).padding(.bottom, 10) 23 | .textInputAutocapitalization(.never) 24 | BasicButton(action: {}, text: "Recover") 25 | } 26 | .textFieldStyle(.roundedBorder) 27 | } 28 | .navigationTitle("12 Words") 29 | .modifier(BackButtonMod()) 30 | } 31 | } 32 | 33 | struct RecoverView_Previews: PreviewProvider { 34 | static var previews: some View { 35 | RecoverView() 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /BdkSwiftSample/SendView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SendView.swift 3 | // IOSBdkAppSample 4 | // 5 | // Created by Sudarsan Balaji on 02/11/21. 6 | // 7 | 8 | import SwiftUI 9 | import Combine 10 | import CodeScanner 11 | 12 | struct SendView: View { 13 | @State var to: String = "" 14 | @State var amount: String = "0" 15 | @State private var isShowingScanner = false 16 | 17 | @Environment(\.presentationMode) var presentationMode 18 | func handleScan(result: Result) { 19 | self.isShowingScanner = false 20 | switch result { 21 | case .success(let code): 22 | self.to = code 23 | case .failure(let error): 24 | print(error) 25 | } 26 | } 27 | let formatter: NumberFormatter = { 28 | let formatter = NumberFormatter() 29 | formatter.numberStyle = .decimal 30 | return formatter 31 | }() 32 | var onSend : (String, UInt64) -> () 33 | var body: some View { 34 | BackgroundWrapper { 35 | VStack { 36 | 37 | 38 | Form { 39 | Section(header: Text("Recipient").textStyle(BasicTextStyle(white: true))) { 40 | TextField("Address", text: $to) 41 | .modifier(BasicTextFieldStyle()) 42 | } 43 | Section(header: Text("Amount (sats)").textStyle(BasicTextStyle(white: true))) { 44 | TextField("Amount", text: $amount) 45 | .modifier(BasicTextFieldStyle()) 46 | .keyboardType(.numberPad) 47 | .onReceive(Just(amount)) { newValue in 48 | let filtered = newValue.filter { "0123456789".contains($0) } 49 | if filtered != newValue { 50 | self.amount = filtered 51 | } 52 | } 53 | } 54 | } 55 | .onAppear { 56 | UITableView.appearance().backgroundColor = .clear } 57 | 58 | Spacer() 59 | BasicButton(action: { self.isShowingScanner = true}, text: "Scan Address") 60 | BasicButton(action: { 61 | onSend(to, (UInt64(amount) ?? 0)) 62 | presentationMode.wrappedValue.dismiss() 63 | }, text: "Broadcast Transaction", color: "Red").disabled(to == "" || (Double(amount) ?? 0) == 0) 64 | } 65 | } 66 | .navigationTitle("Send") 67 | .modifier(BackButtonMod()) 68 | .sheet(isPresented: $isShowingScanner) { 69 | CodeScannerView(codeTypes: [.qr], simulatedData: "Testing1234", completion: self.handleScan)} 70 | } 71 | } 72 | 73 | struct SendView_Previews: PreviewProvider { 74 | static func onSend(to: String, amount: UInt64) { 75 | 76 | } 77 | static var previews: some View { 78 | SendView(onSend: self.onSend) 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /BdkSwiftSample/SettingsView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SettingsView.swift 3 | // MyFirstApp 4 | // 5 | // Created by Paul Miller on 11/4/21. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct SettingsView: View { 11 | @State private var goToWords = false 12 | @State private var goToRecovery = false 13 | let words = "clutch solar sand travel vital fitness hand piece dial flag garment grant" 14 | 15 | var body: some View { 16 | NavigationLink(destination: MnemonicView(words: words), isActive: $goToWords) { EmptyView() } 17 | NavigationLink(destination: RecoverView(), isActive: $goToRecovery) { EmptyView() } 18 | BackgroundWrapper { 19 | Spacer() 20 | Text("Running on Bitcoin Testnet").textStyle(BasicTextStyle(white: true, bold: true)) 21 | Spacer() 22 | BasicButton(action: { goToWords = true }, text: "Create a New Wallet") 23 | BasicButton(action: { goToRecovery = true}, text: "Recover an Existing Wallet") 24 | } 25 | .navigationTitle("Wallet Setup") 26 | .modifier(BackButtonMod()) 27 | 28 | } 29 | } 30 | 31 | struct SettingsView_Previews: PreviewProvider { 32 | static var previews: some View { 33 | SettingsView() 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /BdkSwiftSample/Styles/BackButtonMod.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BackButtonMod.swift 3 | // MyFirstApp 4 | // 5 | // Created by Paul Miller on 11/5/21. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct BackButtonMod: ViewModifier { 11 | @Environment(\.presentationMode) var presentation 12 | func body(content: Content) -> some View { 13 | content 14 | .navigationBarBackButtonHidden(true) 15 | .toolbar(content: { 16 | ToolbarItem (placement: .navigation) { 17 | Image(systemName: "arrow.left") 18 | .foregroundColor(.white) 19 | .shadow(color: Color("Shadow"), radius: 2, x: 2, y: 2) 20 | .onTapGesture { 21 | // code to dismiss the view 22 | self.presentation.wrappedValue.dismiss() 23 | } 24 | } 25 | }) 26 | } 27 | } 28 | 29 | struct BackButtonMod_Previews: PreviewProvider { 30 | static var previews: some View { 31 | Text("Heyy").modifier(BackButtonMod()) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /BdkSwiftSample/Styles/BasicButtonStyle.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BasicButtonStyle.swift 3 | // MyFirstApp 4 | // 5 | // Created by Paul Miller on 11/4/21. 6 | // 7 | import SwiftUI 8 | 9 | struct BasicButtonStyle: ButtonStyle { 10 | var bgColor: Color 11 | 12 | func makeBody(configuration: Self.Configuration) -> some View { 13 | configuration.label 14 | .frame(maxWidth: .infinity, maxHeight: 40) 15 | .foregroundColor(Color("Shadow")) 16 | .background(Color("Primary")) 17 | .cornerRadius(10.0) 18 | .shadow(color: Color("Shadow"), radius: 1, x: 5, y: 5) 19 | .padding(20) 20 | } 21 | } 22 | 23 | struct BasicButtonStyle_Previews: PreviewProvider { 24 | static var previews: some View { 25 | Button(action: {}) { 26 | Text("Hello").textStyle(BasicTextStyle()) 27 | }.buttonStyle(BasicButtonStyle(bgColor: Color("Primary"))) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /BdkSwiftSample/Styles/BasicTextFieldStyle.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BasicTextFieldStyle.swift 3 | // MyFirstApp 4 | // 5 | // Created by Paul Miller on 11/5/21. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct BasicTextFieldStyle: ViewModifier { 11 | func body(content: Content) -> some View { 12 | content 13 | .disableAutocorrection(true) 14 | // .textFieldStyle(.roundedBorder) 15 | .textInputAutocapitalization(.never) 16 | } 17 | } 18 | 19 | struct BasicTextFieldStyle_Previews: PreviewProvider { 20 | static var previews: some View { 21 | Text("TEst") 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /BdkSwiftSample/Styles/BasicTextStyle.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BasicTextStye.swift 3 | // MyFirstApp 4 | // 5 | // Created by Paul Miller on 11/4/21. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct BasicTextStyle: ViewModifier { 11 | var big = false 12 | var white = false 13 | var bold = false 14 | func body(content: Content) -> some View { 15 | content 16 | .font(.system(size: big ? 32 : 14, design: .monospaced).weight(bold ? .bold : .regular)) 17 | .foregroundColor(white ? Color.white : Color("Shadow")) 18 | 19 | } 20 | } 21 | extension Text { 22 | func textStyle(_ style: Style) -> some View { 23 | ModifiedContent(content: self, modifier: style) 24 | } 25 | } 26 | 27 | struct BasicTextStyle_Previews: PreviewProvider { 28 | static var previews: some View { 29 | Text("Hello").textStyle(BasicTextStyle()) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /BdkSwiftSample/TxsView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TxsView.swift 3 | // MyFirstApp 4 | // 5 | // Created by Paul Miller on 11/5/21. 6 | // 7 | 8 | import SwiftUI 9 | import BitcoinDevKit 10 | 11 | extension Date { 12 | func getFormattedDate(format: String) -> String { 13 | let dateformat = DateFormatter() 14 | dateformat.dateFormat = format 15 | return dateformat.string(from: self) 16 | } 17 | } 18 | 19 | struct TxsView: View { 20 | 21 | @EnvironmentObject var viewModel: WalletViewModel 22 | 23 | var body: some View { 24 | BackgroundWrapper { 25 | ScrollView { 26 | if viewModel.transactions.isEmpty { 27 | Text("No transactions yet.").padding() 28 | } else { 29 | ForEach(viewModel.transactions, id: \.self.txid) { transaction in 30 | SingleTxView(transactionDetails: transaction) 31 | } 32 | } 33 | } 34 | } 35 | .navigationTitle("Transactions") 36 | .modifier(BackButtonMod()) 37 | } 38 | } 39 | 40 | struct TxsView_Previews: PreviewProvider { 41 | static var previews: some View { 42 | TxsView() 43 | .environmentObject(WalletViewModel()) 44 | } 45 | } 46 | 47 | -------------------------------------------------------------------------------- /BdkSwiftSample/WalletView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // MyFirstApp 4 | // 5 | // Created by Paul Miller on 11/4/21. 6 | // 7 | 8 | import SwiftUI 9 | import Combine 10 | import BitcoinDevKit 11 | 12 | struct WalletView: View { 13 | @EnvironmentObject var viewModel: WalletViewModel 14 | 15 | init() { 16 | UINavigationBar.appearance().largeTitleTextAttributes = [.font : UIFont.monospacedSystemFont(ofSize: 28, weight: .bold), .foregroundColor: UIColor.white] 17 | } 18 | 19 | var body: some View { 20 | NavigationView { 21 | switch viewModel.state { 22 | case .empty: 23 | VStack {Text("error")} 24 | case .failed(_): 25 | VStack {Text("error")} 26 | case .loading: 27 | VStack {Text("error")} 28 | case .loaded(_, _): 29 | HomeView() 30 | } 31 | }.onAppear(perform: viewModel.load) 32 | } 33 | } 34 | 35 | struct ContentView_Previews: PreviewProvider { 36 | static var previews: some View { 37 | WalletView() 38 | .environmentObject(WalletViewModel()) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /BdkSwiftSample/WalletViewModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // WalletViewModel.swift 3 | // IOSBdkAppSample 4 | // 5 | // Created by Sudarsan Balaji on 29/10/21. 6 | // 7 | 8 | import Foundation 9 | import BitcoinDevKit 10 | 11 | extension TransactionDetails: Comparable { 12 | public static func < (lhs: TransactionDetails, rhs: TransactionDetails) -> Bool { 13 | 14 | let lhs_timestamp: UInt64 = lhs.confirmationTime?.timestamp ?? UInt64.max; 15 | let rhs_timestamp: UInt64 = rhs.confirmationTime?.timestamp ?? UInt64.max; 16 | 17 | return lhs_timestamp < rhs_timestamp 18 | } 19 | } 20 | 21 | extension TransactionDetails: Equatable { 22 | public static func == (lhs: TransactionDetails, rhs: TransactionDetails) -> Bool { 23 | 24 | let lhs_timestamp: UInt64 = lhs.confirmationTime?.timestamp ?? UInt64.max; 25 | let rhs_timestamp: UInt64 = rhs.confirmationTime?.timestamp ?? UInt64.max; 26 | 27 | return lhs_timestamp == rhs_timestamp 28 | } 29 | } 30 | 31 | class WalletViewModel: ObservableObject { 32 | enum State { 33 | case empty 34 | case loading 35 | case failed(Error) 36 | case loaded(Wallet, Blockchain) 37 | } 38 | 39 | enum SyncState { 40 | case empty 41 | case syncing 42 | case synced 43 | case failed(Error) 44 | } 45 | 46 | private(set) var key = "private_key" 47 | @Published private(set) var state = State.empty 48 | @Published private(set) var syncState = SyncState.empty 49 | @Published private(set) var balance: UInt64 = 0 50 | @Published private(set) var balanceText = "sync plz" 51 | @Published private(set) var transactions: [BitcoinDevKit.TransactionDetails] = [] 52 | 53 | func load() { 54 | state = .loading 55 | 56 | DispatchQueue.global().async { [weak self] in 57 | guard let self = self else { return } 58 | 59 | let db = DatabaseConfig.memory 60 | do { 61 | let descriptor = try Descriptor.init(descriptor: "wpkh(tprv8ZgxMBicQKsPeSitUfdxhsVaf4BXAASVAbHypn2jnPcjmQZvqZYkeqx7EHQTWvdubTSDa5ben7zHC7sUsx4d8tbTvWdUtHzR8uhHg2CW7MT/*)", network: Network.testnet) 62 | let electrum = ElectrumConfig(url: "ssl://electrum.blockstream.info:60002", socks5: nil, retry: 5, timeout: nil, stopGap: 10, validateDomain: true) 63 | let blockchainConfig = BlockchainConfig.electrum(config: electrum) 64 | let blockchain = try Blockchain(config: blockchainConfig) 65 | let wallet = try Wallet(descriptor: descriptor, changeDescriptor: nil, network: Network.testnet, databaseConfig: db) 66 | 67 | DispatchQueue.main.async { 68 | self.state = State.loaded(wallet, blockchain) 69 | } 70 | } catch let error { 71 | DispatchQueue.main.async { 72 | self.state = State.failed(error) 73 | } 74 | } 75 | } 76 | } 77 | 78 | func sync() { 79 | self.balanceText = "syncing" 80 | 81 | DispatchQueue.global().async { [weak self] in 82 | guard let self = self else { return } 83 | 84 | switch self.state { 85 | case .loaded(let wallet, let blockchain): 86 | DispatchQueue.main.async { 87 | self.syncState = .syncing 88 | } 89 | do { 90 | // TODO use this progress update to show "syncing" 91 | try wallet.sync(blockchain: blockchain, progress: nil) 92 | let balance = try wallet.getBalance().confirmed 93 | let wallet_transactions: [TransactionDetails] = try wallet.listTransactions(includeRaw: false) 94 | 95 | DispatchQueue.main.async { 96 | self.syncState = .synced 97 | self.balance = balance 98 | self.balanceText = String(format: "%.8f", Double(self.balance) / Double(100000000)) 99 | self.transactions = wallet_transactions.sorted().reversed() 100 | } 101 | } catch let error { 102 | print(error) 103 | DispatchQueue.main.async { 104 | self.syncState = .failed(error) 105 | } 106 | } 107 | default: do { } 108 | print("default") 109 | } 110 | } 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Paul Miller 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Bdk Swift Sample app 2 | 3 | | home | receive | 4 | | -------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- | 5 | | ![](https://user-images.githubusercontent.com/543668/145661411-74b74b5c-77be-49ec-b305-9c4d70ac038a.png) | ![](https://user-images.githubusercontent.com/543668/145661417-85a9f11d-f334-426a-bc77-f7ee80cf218e.png) | 6 | 7 | This project is an example app / testbed for `bdk` (Bitcoin Dev Kit) Swift bindings. Features include syncing to testnet, sending and receiving fake Bitcoin, and QR code scanning. It started out life as a hackathon project by @futurepaul and @konjoinfinity. 8 | 9 | The basic logic has been mostly borrowed from the bdk-ffi sample app by @artfuldev. 10 | 11 | Bdk Swift Sample App is strongly inspired by @thunderbiscuit's [Bitcoindevkit Android Demo Wallet](https://github.com/thunderbiscuit/bitcoindevkit-android-sample-app) with the primary differences being the choice of color scheme and operating system. 12 | 13 | Check these out: 14 | - [bdk (where it all begins!)](https://github.com/bitcoindevkit/bdk) 15 | - [bdk-ffi](https://github.com/bitcoindevkit/bdk-ffi) 16 | - [bdk-swift](https://github.com/bitcoindevkit/bdk-swift) 17 | --------------------------------------------------------------------------------