Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/swift-sdk/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ let package = Package(
name: "SwiftDashSDK",
dependencies: ["DashSDKFFI"],
path: "Sources/SwiftDashSDK",
exclude: ["KeyWallet/README.md", "PlatformWallet/README.md"],
exclude: ["KeyWallet/README.md"],
linkerSettings: [.linkedFramework("SystemConfiguration")]
),

Expand Down
39 changes: 0 additions & 39 deletions packages/swift-sdk/Sources/SwiftDashSDK/Address/Addresses.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1210,45 +1210,6 @@ public class Addresses: @unchecked Sendable {
return PlatformAddressInfosResult(infos: infos)
}

// MARK: - Convenience Methods

/// Get the balance for a single address
///
/// - Parameter addressBytes: Address bytes (21 bytes)
/// - Returns: Balance in credits, or nil if address not found
/// - Throws: SDKError if the query fails
public func getBalance(addressBytes: Data) throws -> UInt64? {
return try getInfo(addressBytes: addressBytes)?.balance
}

/// Get the nonce for a single address
///
/// - Parameter addressBytes: Address bytes (21 bytes)
/// - Returns: Nonce value, or nil if address not found
/// - Throws: SDKError if the query fails
public func getNonce(addressBytes: Data) throws -> UInt32? {
return try getInfo(addressBytes: addressBytes)?.nonce
}

/// Check if an address exists on Platform
///
/// - Parameter addressBytes: Address bytes (21 bytes)
/// - Returns: true if the address has been used on Platform
/// - Throws: SDKError if the query fails
public func exists(addressBytes: Data) throws -> Bool {
return try getInfo(addressBytes: addressBytes) != nil
}

/// Get total balance across multiple addresses
///
/// - Parameter addressesBytesList: Array of address bytes
/// - Returns: Total balance in credits across all found addresses
/// - Throws: SDKError if the query fails
public func getTotalBalance(addressesBytesList: [Data]) throws -> UInt64 {
let result = try getInfos(addressesBytesList: addressesBytesList)
return result.totalBalance
}

// MARK: - Identity State Transitions (Address-Related)

/// Top up an identity using Platform address balances
Expand Down
41 changes: 0 additions & 41 deletions packages/swift-sdk/Sources/SwiftDashSDK/ConcurrencyCompat.swift

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import Foundation
import LocalAuthentication
import Security

// MARK: - Wallet Storage
Expand All @@ -26,9 +25,6 @@ import Security
/// with the original name/description after a reinstall.
/// * Enumeration of stored wallet ids (used by the orphan-mnemonic
/// recovery flow in `ContentView`).
/// * Biometric-protected seed stash at `wallet.biometric` — not yet
/// wired to a caller but kept because it's a different category
/// (hardware-protected rather than a legacy PIN construct).
public class WalletStorage {
/// Unified keychain service name for the app. Everything the
/// SDK writes — per-wallet mnemonics (here), identity private
Expand All @@ -55,7 +51,6 @@ public class WalletStorage {
/// user-facing wallet name and description from the keychain
/// even though SwiftData was wiped.
public static let metadataAccountPrefix = "wallet.metadata"
private let biometricKeychainAccount = "wallet.biometric"

public init() {}

Expand Down Expand Up @@ -371,66 +366,6 @@ public class WalletStorage {
return data
}

// MARK: - Biometric Protection

public func enableBiometricProtection(for seed: Data) throws {
var error: Unmanaged<CFError>?
guard let access = SecAccessControlCreateWithFlags(
nil,
kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
.biometryCurrentSet,
&error
) else {
throw WalletStorageError.biometricSetupFailed
}

let deleteQuery: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrService as String: keychainService,
kSecAttrAccount as String: biometricKeychainAccount
]

let deleteStatus = SecItemDelete(deleteQuery as CFDictionary)
guard deleteStatus == errSecSuccess || deleteStatus == errSecItemNotFound else {
throw WalletStorageError.keychainError(deleteStatus)
}

let addQuery: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrService as String: keychainService,
kSecAttrAccount as String: biometricKeychainAccount,
kSecValueData as String: seed,
kSecAttrAccessControl as String: access
]

let status = SecItemAdd(addQuery as CFDictionary, nil)
guard status == errSecSuccess else {
throw WalletStorageError.keychainError(status)
}
}

public func retrieveSeedWithBiometric() throws -> Data {
let context = LAContext()
context.localizedReason = "Authenticate to access your wallet"
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrService as String: keychainService,
kSecAttrAccount as String: biometricKeychainAccount,
kSecReturnData as String: true,
kSecUseAuthenticationContext as String: context
]

var result: AnyObject?
let status = SecItemCopyMatching(query as CFDictionary, &result)

guard status == errSecSuccess,
let seed = result as? Data else {
throw WalletStorageError.biometricAuthenticationFailed
}

return seed
}

// MARK: - Legacy Cleanup

/// Best-effort scrub of keychain residue from prior app
Expand Down Expand Up @@ -574,19 +509,13 @@ public struct WalletKeychainMetadata: Codable, Equatable {
public enum WalletStorageError: LocalizedError {
case keychainError(OSStatus)
case mnemonicNotFound
case biometricSetupFailed
case biometricAuthenticationFailed

public var errorDescription: String? {
switch self {
case .keychainError(let status):
return "Keychain error: \(status)"
case .mnemonicNotFound:
return "Mnemonic not found"
case .biometricSetupFailed:
return "Failed to setup biometric protection"
case .biometricAuthenticationFailed:
return "Biometric authentication failed"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ import SwiftData
/// Result: every `KeychainSigner` instance leaked forever. The
/// current `passUnretained` shape removes the leak at the cost
/// of the explicit keepalive contract above.
public final class KeychainSigner: Signer, @unchecked Sendable {
public final class KeychainSigner: @unchecked Sendable {
final class AdditionalSigningKeyEntry: @unchecked Sendable {
let publicKey: Data
private var privateKeyBytes: [UInt8]
Expand Down Expand Up @@ -951,12 +951,6 @@ public final class KeychainSigner: Signer, @unchecked Sendable {
return .failure(.ffiSignFailed(message: String(describing: error)))
}
}

// MARK: - Signer protocol conformance (legacy)

public func canSign(identityPublicKey: Data) -> Bool {
canSign(publicKey: identityPublicKey, keyType: KeyType.ecdsaSecp256k1.rawValue)
}
}

// MARK: - C-ABI trampolines
Expand Down
21 changes: 0 additions & 21 deletions packages/swift-sdk/Sources/SwiftDashSDK/FFI/Signer.swift

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -149,66 +149,6 @@ private func createPublicKeyHandle(from key: IdentityPublicKey, operation: Strin
@MainActor
extension SDK {

// MARK: - Helpers (nonisolated)

/// JSON-encode a contract sub-payload off-actor for FFI hand-off.
/// Used by `dataContractCreate` to serialize document schemas,
/// token schemas, groups, keywords, and config — every payload
/// the FFI accepts as a JSON string. `allowEmpty: false` returns
/// `nil` for empty containers so callers can drop the parameter
/// entirely (the FFI treats a missing pointer as "field absent",
/// which lets the V1 deserializer fall back to its serde default).
nonisolated fileprivate static func encodeContractField(
_ value: Any,
fieldName: String,
allowEmpty: Bool
) throws -> String? {
if !allowEmpty {
if let dict = value as? [String: Any], dict.isEmpty { return nil }
if let arr = value as? [Any], arr.isEmpty { return nil }
}
guard JSONSerialization.isValidJSONObject(value) else {
throw SDKError.serializationError("\(fieldName) is not JSON-serializable")
}
guard let data = try? JSONSerialization.data(withJSONObject: value),
let str = String(data: data, encoding: .utf8) else {
throw SDKError.serializationError("Failed to serialize \(fieldName)")
}
return str
}

/// Run `body` with parallel C-string pointers for each input,
/// where `nil` Swift entries map to NULL pointers. The caller
/// receives an array `ptrs` whose `ptrs[i]` is either a valid
/// `UnsafePointer<CChar>` for the duration of the call or
/// `nil`. Implemented recursively over `inputs.indices` so
/// every backing `String`'s lifetime extends through the
/// entire body — six nested `withCString` calls in source form
/// without the visual nesting.
nonisolated fileprivate static func withOptionalCStrings<R>(
_ inputs: [String?],
_ body: ([UnsafePointer<CChar>?]) -> R
) -> R {
var collected: [UnsafePointer<CChar>?] = Array(repeating: nil, count: inputs.count)
func step(_ index: Int) -> R {
if index == inputs.count {
return body(collected)
}
switch inputs[index] {
case .some(let s):
return s.withCString { ptr in
collected[index] = ptr
let result = step(index + 1)
collected[index] = nil
return result
}
case .none:
return step(index + 1)
}
}
return step(0)
}

// MARK: - Identity Handle Management

/// Convert a DPPIdentity to an identity handle
Expand Down Expand Up @@ -1382,17 +1322,6 @@ extension SDK {

// MARK: - Token State Transitions

/// Transfer tokens between identities
public func tokenTransfer(
tokenId: String,
fromIdentityId: String,
toIdentityId: String,
amount: UInt64
) async throws -> (senderBalance: UInt64, receiverBalance: UInt64) {
// TODO: Implement when FFI binding is available
throw SDKError.notImplemented("Token transfer not yet implemented")
}

/// Mint new tokens
public func tokenMint(
contractId: String,
Expand Down

This file was deleted.

Loading
Loading