diff --git a/scripts/build-swift.sh b/scripts/build-swift.sh index 97d12f14..2c9cb9dd 100755 --- a/scripts/build-swift.sh +++ b/scripts/build-swift.sh @@ -24,9 +24,10 @@ echo "" echo "🔧 Step 2/3: Generating Swift bindings..." mkdir -p "$GENERATED_DIR" -uniffi-bindgen generate \ +cargo run -p uniffi-bindgen generate \ --library target/release/libidkit.dylib \ --language swift \ + --no-format \ --out-dir "$GENERATED_DIR" echo "✅ Generated Swift bindings to: $GENERATED_DIR" diff --git a/swift/Examples/IDKitSampleApp/IDKitSampleApp/ContentView.swift b/swift/Examples/IDKitSampleApp/IDKitSampleApp/ContentView.swift index 38b94838..0fd981d0 100644 --- a/swift/Examples/IDKitSampleApp/IDKitSampleApp/ContentView.swift +++ b/swift/Examples/IDKitSampleApp/IDKitSampleApp/ContentView.swift @@ -21,6 +21,7 @@ enum SampleLegacyPreset: String, CaseIterable, Identifiable { case document case device case selfieCheck = "selfie check" + case identityCheckWithProofOfHumanity = "identity check with proof of humanity" var id: String { rawValue } @@ -36,6 +37,15 @@ enum SampleLegacyPreset: String, CaseIterable, Identifiable { deviceLegacy(signal: signal) case .selfieCheck: selfieCheckLegacy(signal: signal) + case .identityCheckWithProofOfHumanity: + identityCheck( + attributes: [ + .minimumAge(21), + .nationality("JPN"), + .documentType(.passport), + ], + requireProofOfHumanity: true + ) } } } @@ -76,7 +86,7 @@ struct ContentView: View { } .pickerStyle(.segmented) - Picker("Legacy preset", selection: $model.legacyPreset) { + Picker("Preset", selection: $model.legacyPreset) { ForEach(SampleLegacyPreset.allCases) { preset in Text(preset.rawValue).tag(preset) } @@ -201,7 +211,7 @@ final class SampleModel: ObservableObject { deepLinkReceivedForPendingRequest = false print("IDKit connector URL: \(request.connectorURL.absoluteString)") - log("Using legacy preset: \(legacyPreset.rawValue)") + log("Using preset: \(legacyPreset.rawValue)") log("Generated request ID: \(request.requestID.uuidString)") log("Configured return_to callback: \(returnToURL)") startPollingForRequest(request: request, reason: "request generation") diff --git a/swift/README.md b/swift/README.md index 70171361..db3882ba 100644 --- a/swift/README.md +++ b/swift/README.md @@ -74,6 +74,23 @@ let request = try IDKit .preset(selfieCheckLegacy(signal: "user-123")) ``` +For document-based identity attestation, use: + +```swift +let request = try IDKit + .request(config: config) + .preset( + identityCheck( + attributes: [ + .minimumAge(21), + .nationality("JPN"), + .documentType(.passport), + ], + requireProofOfHumanity: true + ) + ) +``` + ## Canonical Swift API - Entry points: diff --git a/swift/Sources/IDKit/IDKit.swift b/swift/Sources/IDKit/IDKit.swift index 8a011e46..a16e88f1 100644 --- a/swift/Sources/IDKit/IDKit.swift +++ b/swift/Sources/IDKit/IDKit.swift @@ -475,6 +475,19 @@ public func selfieCheckLegacy(signal: String? = nil) -> Preset { .selfieCheckLegacy(signal: signal) } +/// Returns the identity check preset. +/// +/// This preset requires World ID 4.0-compatible clients. +public func identityCheck( + attributes: [IdentityAttribute], + requireProofOfHumanity: Bool = false +) -> Preset { + .identityCheck( + attributes: attributes, + requireProofOfHumanity: requireProofOfHumanity + ) +} + // TODO: Re-enable when World ID 4.0 is live // private struct CredentialRequestJSON: Encodable { // let type: String diff --git a/swift/Tests/IDKitTests/IDKitTests.swift b/swift/Tests/IDKitTests/IDKitTests.swift index e1628e14..2e9d813c 100644 --- a/swift/Tests/IDKitTests/IDKitTests.swift +++ b/swift/Tests/IDKitTests/IDKitTests.swift @@ -241,6 +241,14 @@ func legacyPresetHelpers() { let doc = documentLegacy(signal: "z") let device = deviceLegacy(signal: "d") let face = selfieCheckLegacy(signal: "f") + let identity = identityCheck( + attributes: [ + .minimumAge(21), + .nationality("JPN"), + .documentType(.passport) + ], + requireProofOfHumanity: true + ) switch orb { case .orbLegacy(let signal): @@ -276,6 +284,19 @@ func legacyPresetHelpers() { case .orbLegacy, .secureDocumentLegacy, .documentLegacy, .deviceLegacy, .identityCheck: Issue.record("Expected selfieCheckLegacy preset") } + + switch identity { + case let .identityCheck(attributes, requireProofOfHumanity): + let expected: [IdentityAttribute] = [ + .minimumAge(21), + .nationality("JPN"), + .documentType(.passport) + ] + #expect(attributes == expected) + #expect(requireProofOfHumanity) + case .orbLegacy, .secureDocumentLegacy, .documentLegacy, .deviceLegacy, .selfieCheckLegacy: + Issue.record("Expected identityCheck preset") + } } // TODO: Re-enable when World ID 4.0 is live