How to check SPL token balance on Solana

Issue #863 We will check USDC token balance on Solana testnet. Firstly, we will use https://usdcfaucet.com/ to airdrop some USDC tokens into our wallet. Secondly, we check USDC token mint address on testnet cluster using Solana Explorer https://explorer.solana.com/address/CpMah17kQEL2wqyMKt3mZBdTnZbkbfx4nqmQMFDP5vwp?cluster=testnet Then we make an RPC call to POST https://api.testnet.solana.comhttps://api.testnet.solana.com using method getTokenAccountsByOwner, passing our wallet address and the token mint address { "jsonrpc": "2.0", "id": 1, "method": "getTokenAccountsByOwner", "params": [ "53THxwqa9qF3cn46wHVKbGMM8hUpZDJE5jS3T1qVL5bc", { "mint": "CpMah17kQEL2wqyMKt3mZBdTnZbkbfx4nqmQMFDP5vwp" }, { "encoding": "jsonParsed" } ] } The response looks like below....

February 7, 2022 路 2 min 路 Khoa Pham

How to use subscript in Swift

Issue #861 Make it easy to access common cases, for example UserDefaults extension UserDefaults { enum Key: String { case hasBackup } subscript(key: Key) -> Bool { get { bool(forKey: key.rawValue) } set { set(newValue, forKey: key.rawValue) } } } UserDefaults.standard.hasBackup] = true

February 5, 2022 路 1 min 路 Khoa Pham

How to encode JSON dictionary into JSONEncoder

Issue #860 JSONEncoder deals with type-safe, so we need to declare an enum JSONValue for all possible types. We also need a custom initializer to init JSONValue from a JSON Dictionary import Foundation enum JSONValue { case string(String) case int(Int) case double(Double) case bool(Bool) case object([String: JSONValue]) case array([JSONValue]) } extension JSONValue: Encodable { public func encode(to encoder: Encoder) throws { var container = encoder.singleValueContainer() switch self { case .string(let string): try container....

February 4, 2022 路 2 min 路 Khoa Pham

How to parse Apple Pay PKPayment in Swift

Issue #859 To parse PKPayment and used with Wyre CreateAppleOrder API, we can declare some Encodable structs import PassKit import Foundation struct PaymentObject: Encodable { var billingContact: Contact? var shippingContact: Contact? var token: JSONValue } extension PaymentObject { struct Contact: Encodable { var addressLines: [String]? var country: String? var countryCode: String? var familyName: String? var givenname: String? var locality: String? var postalCode: String? var administrativeArea: String? var subAdministrativeArea: String? var subLocality: String?...

February 4, 2022 路 1 min 路 Khoa Pham

How to pop multiple level with NavigationView and NavigationLink in SwiftUI

Issue #858 Use isActive and isDetailLink(false) Use Introspect .introspectNavigationController { nav in self.nav = nav } Read more https://www.cuvenx.com/post/swiftui-pop-to-root-view

January 27, 2022 路 1 min 路 Khoa Pham

How to generate Solana wallet acount in Swift

Issue #857 Use Solana.swift and Mnemonic seed phrase. For production, change endpoint to mainnet import UIKit import Solana import KeychainAccess enum SolanaError: Swift.Error { case accountFailed case unauthorized } final class SolanaClient { static let shared = SolanaClient() final class SolanaClient { static let shared = SolanaClient() private let solana: Solana private let accountStorage = KeychainAccountStorage() private let seedPharser = SeedPhraser() private let endpoint: RPCEndpoint = .devnetSolana private let network: NetworkingRouter init() { self....

January 26, 2022 路 2 min 路 Khoa Pham

How to use Apple Pay in iOS

Issue #856 Use PKPaymentRequest and PKPaymentAuthorizationViewController @MainActor final class WalletViewModel: NSObject, ObservableObject { var canMakePayments: Bool { PKPaymentAuthorizationViewController.canMakePayments() } func showApplePay(amount: Amount, from window: UIWindow) { let request = PKPaymentRequest() request.supportedNetworks = [PKPaymentNetwork.amex, .discover, .masterCard, .visa] request.countryCode = "US" request.currencyCode = "USD" request.merchantIdentifier = "merchant.\(Bundle.main.bundleIdentifier!)" request.merchantCapabilities = .capability3DS let item = PKPaymentSummaryItem(label: "Add Cash", amount: amount.toNsDecimal) request.paymentSummaryItems = [item] guard let vc = PKPaymentAuthorizationViewController(paymentRequest: request) else { return } vc.delegate = self window....

January 17, 2022 路 1 min 路 Khoa Pham

How to show QR code in SwiftUI

Issue #855 Use CoreImage to generate QR image import SwiftUI import CoreImage.CIFilterBuiltins struct QRView: View { let qrCode: String @State private var image: UIImage? var body: some View { ZStack { if let image = image { Image(uiImage: image) .resizable() .interpolation(.none) .frame(width: 210, height: 210) } } .onAppear { generateImage() } } private func generateImage() { guard image == nil else { return } let context = CIContext() let filter = CIFilter....

January 15, 2022 路 1 min 路 Khoa Pham

How to not encode with Enum key in Swift

Issue #854 If you use enum case as key in Dictionary, JSONEncoder will encode it as Array. For example enum Vehicle: String, Codable { case car case truck } struct Container: Codable { var map: [Vehicle: String] } struct Container2: Codable { var map: [String: String] } let container = Container(map: [ .car: "Car 1" ]) let container2 = Container2(map: [ "car": "Car 1" ]) let data = try! JSONEncoder().encode(container) print(String(data: data, encoding: ....

January 10, 2022 路 2 min 路 Khoa Pham

How to disable with ButtonStyle in SwiftUI

Issue #853 With ButtonStyle, the disabled modifier does not seem to work, we need to use allowsHitTesting. import SwiftUI struct ActionButtonStyle: ButtonStyle { func makeBody(configuration: Configuration) -> some View { HStack { Text("Button") } .padding() .disabled(true) // does not work .allowsHitTesting(false) } } We need to call disabled outside, after buttonStyle. In case we have onTapGesture on the entire view, touching on that disabled button will also trigger our whole view action, which is not what we want....

December 4, 2021 路 1 min 路 Khoa Pham

How to query document id in array in Firestore

Issue #852 Supposed we have Book object struct Book: Identifiable, Codable, Hashable { @DocumentID var id: String? } We should use FieldPath instead of id for query let booksRef: CollectionReference = ... let ids: [String] = ... booksRef .whereField( FieldPath.documentID(), in: ids )

November 28, 2021 路 1 min 路 Khoa Pham

How to provide default Codable in Swift

Issue #851 Use DefaultValue to provide defaultValue in our property wrapper DefaultCodable public protocol DefaultValue { associatedtype Value: Codable static var defaultValue: Value { get } } public enum DefaultBy { public enum True: DefaultValue { public static let defaultValue = true } public enum False: DefaultValue { public static let defaultValue = false } } @propertyWrapper public struct DefaultCodable<T: DefaultValue> { public var wrappedValue: T.Value public init(wrappedValue: T.Value) { self....

October 23, 2021 路 1 min 路 Khoa Pham

How to use Picker with optional selection in SwiftUI

Issue #849 We need to explicitly specify optional in tag extension AVCaptureDevice: Identifiable { public var id: String { uniqueID } } @State var device: AVCaptureDevice? Picker("Camera", selection: $device) { ForEach(manager.devices) { d in Text(d.localizedName) .tag(AVCaptureDevice?.some(d)) } }

September 30, 2021 路 1 min 路 Khoa Pham

How to scale system font size to support Dynamic Type

Issue #847 We should use Dynamic Font Type as much as possible, as per Typography guide and https://www.iosfontsizes.com/ But in case we have to use a specific font, we can scale it with UIFontMetrics import SwiftUI import UIKit extension Font { static func system( scaledSize size: CGFloat, weight: Font.Weight = .regular, design: Font.Design = .default ) -> Font { Font.system( size: UIFontMetrics.default.scaledValue(for: size), weight: weight, design: design ) } } Then instead of...

September 2, 2021 路 1 min 路 Khoa Pham

How to show suffix text in TextField in SwiftUI

Issue #845 Suppose we have struct Payment as the state, we declare custom Binding<String> that derives from our state. struct Payment { var amount: Int = 0 } To show our suffix view, we use .fixedSize(horizontal: true, vertical: false) to constrain our TextField to fit content, and to avoid it to grow outside our frame, we constrain a max limit, like 10_000 in this case. An interesting thing is we divide by 10 to not let the newly typed digit enter if the amount is above our limit...

August 24, 2021 路 1 min 路 Khoa Pham

How to show currency symbol in TextField in SwiftUI

Issue #844 Use custom Binding and validate the text. In case of zero, return empty string to let TextField display placeholder var textField: some View { let text = Binding<String>( get: { state.amount > 0 ? "$\(state.amount)" : "" }, set: { text in let text = text.replacingOccurrences(of: "$", with: "") state.amount = Int(text) ?? 0 } ) return TextField("$0", text: text) .keyboardType(.numberPad) .font(.system(size: 50, weight: .medium, design: .monospaced)) .foregroundColor(Asset.textPrimary.color) ....

August 24, 2021 路 1 min 路 Khoa Pham

How to read safe area insets in SwiftUI

Issue #842 Declare EnvironmentKey and read safeAreaInsets from key window in connectedScenes struct SafeAreaInsetsKey: EnvironmentKey { static var defaultValue: EdgeInsets { UIApplication.shared.keyWindow?.safeAreaInsets.swiftUIInsets ?? EdgeInsets() } } private extension UIEdgeInsets { var swiftUIInsets: EdgeInsets { EdgeInsets(top: top, leading: left, bottom: bottom, trailing: right) } } private extension UIApplication { var keyWindow: UIWindow? { connectedScenes .compactMap { $0 as? UIWindowScene } .flatMap { $0.windows } .first { $0.isKeyWindow } } } struct MessageBar: View { @Environment(\....

August 20, 2021 路 1 min 路 Khoa Pham

How to make tab strip with enum cases in SwiftUI

Issue #841 Declare generic on RawRepresentable import SwiftUI struct TabStrip<T: RawRepresentable & Hashable>: View where T.RawValue == String { let values: [T] @Binding var selected: T var body: some View { ScrollView(.horizontal, showsIndicators: false) { LazyHStack(spacing: 24) { ForEach(values, id: \.self) { value in Button(action: { selected = value }) { Text(value.rawValue) .foregroundColor(selected == value ? Asset.textPrimary.color : Asset.textSecondary.color) .fontWeight(selected == value ? .semibold : .regular) .padding(6) } .buttonStyle(PlainButtonStyle()) } } } ....

August 19, 2021 路 1 min 路 Khoa Pham

How to replace multiple regex matches in Swift

Issue #840 Used to replace credit card regex 30[0-5]#-######-###L in EasyFake We can use ? to have non-greedy behavior, or I here use square bracket to fine-tune the expression \{[\d*,]*\d*\} Also, I need to reversed the matches because each replacement makes the next range incorrect extension String { func replacingHash() -> String { self .map { c in guard c == "#" else { return String(c) } let number = Int....

August 11, 2021 路 1 min 路 Khoa Pham

How to move files with Swift script

Issue #839 Use locales data from faker.js to https://github.com/onmyway133/EasyFake, renaming files since files, regardless of sub directories in Xcode, must have different name. We use enumerator API on FileManager to traverse all files in all sub-directories import Foundation let localesURL = URL(fileURLWithPath: FileManager.default.currentDirectoryPath) .appendingPathComponent("Sources/EasyFake/Resources/locales") let manager = FileManager.default manager.enumerator(atPath: localesURL.path)?.forEach { path in guard let path = path as? String else { return } let url = URL(fileURLWithPath: path, relativeTo: localesURL) guard url....

August 10, 2021 路 1 min 路 Khoa Pham