Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
647059d
Fix Swift XCFramework header layout
Jun 16, 2026
7350d5e
Expose bridge debug payload in Swift and Kotlin
Jun 16, 2026
fb26df3
Avoid duplicate Swift modulemaps
Jun 16, 2026
0b10a07
Merge branch 'main' into expose-swift-debug-payload
kchaw2005 Jun 17, 2026
3d00219
"made cleaner looking entry points for the debugging payload functions"
kchaw2005 Jun 17, 2026
f423f11
feat(swift): added uniffi bridgePaylod records for debugging and so …
kchaw2005 Jun 17, 2026
62a93a3
made helper extensions to cleanly view possible credentials easier in…
kchaw2005 Jun 17, 2026
401c95e
Merge branch 'expose-swift-debug-payload' of github.com:worldcoin/idk…
kchaw2005 Jun 17, 2026
47f8a1e
Refactor bridge debug payload to project from the internal builder (B…
kchaw2005 Jun 18, 2026
fb04672
removed duplicate bridgeDebugPayload functions in favor of extending …
kchaw2005 Jun 18, 2026
c95cca3
moved extension into real idbuilder class with disclaimer
kchaw2005 Jun 18, 2026
111c1ec
add errors flag for clippy
kchaw2005 Jun 18, 2026
b6dfe3b
Merge branch 'main' into expose-swift-debug-payload
kchaw2005 Jun 18, 2026
260e72c
updated kotlin sdk to support debugging payload structs and methods
kchaw2005 Jun 18, 2026
d3aa2f1
Merge branch 'expose-swift-debug-payload' of github.com:worldcoin/idk…
kchaw2005 Jun 18, 2026
e104f1c
fix(kotlin): rename DebugSpecification variants to avoid Preset shado…
kchaw2005 Jun 18, 2026
a87840c
refactor rust types
Takaros999 Jun 18, 2026
377b622
update swift/kotlin API
Takaros999 Jun 18, 2026
7beed69
style: run cargo fmt on bridge.rs
kchaw2005 Jun 18, 2026
fcb6329
fix clippy foramtting
kchaw2005 Jun 18, 2026
c7b7ea4
format for clippy
kchaw2005 Jun 18, 2026
2775bbb
fix clippy foramtting
kchaw2005 Jun 18, 2026
d6bd916
fix identityattributes -> identityAttributeWrapper ref
kchaw2005 Jun 18, 2026
dc064a7
we didn't need a wrapper for IdentityAttribute type because it alread…
kchaw2005 Jun 18, 2026
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
33 changes: 33 additions & 0 deletions kotlin/bindings/src/main/kotlin/com/worldcoin/idkit/IdKit.kt
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,13 @@ typealias DocumentType = uniffi.idkit_core.DocumentType
typealias IdentityAttribute = uniffi.idkit_core.IdentityAttribute
typealias ConnectUrlMode = uniffi.idkit_core.ConnectUrlMode

/** Typed projection of the bridge request payload, exposed for building test fixtures. */
typealias BridgeRequestPayload = uniffi.idkit_core.BridgeRequestPayloadWrapper
/** Protocol-level proof request inside a [BridgeRequestPayload]. */
typealias ProofRequest = uniffi.idkit_core.ProofRequestWrapper
/** A per-credential request line item inside a [ProofRequest]. */
typealias CredentialRequestItem = uniffi.idkit_core.CredentialRequestWrapper

data class IDKitRequestConfig(
val appId: String,
val action: String,
Expand Down Expand Up @@ -258,6 +265,26 @@ object IDKit {
return IDKitBuilder(nativeRequest(config.toNative()))
}

/**
* Builds the bridge request payload from a preset without opening a network
* connection. Intended for building test fixtures.
*/
fun createBridgePayloadFromPresets(
config: IDKitRequestConfig,
preset: Preset,
): BridgeRequestPayload =
nativeRequest(config.toNative()).bridgeRequestPayloadFromPreset(preset)

/**
* Builds the bridge request payload from custom constraints without opening a
* network connection. Intended for building test fixtures.
*/
fun createBridgePayloadFromConstraints(
config: IDKitRequestConfig,
constraints: uniffi.idkit_core.ConstraintNode,
): BridgeRequestPayload =
nativeRequest(config.toNative()).bridgeRequestPayload(constraints)

// TODO: Re-enable when World ID 4.0 is live
// fun createSession(config: IDKitSessionConfig): IDKitBuilder {
// require(config.appId.isNotBlank()) { "app_id is required" }
Expand Down Expand Up @@ -397,3 +424,9 @@ fun idkitResultToJson(result: IDKitResult): String = nativeIdkitResultToJson(res
fun idkitResultFromJson(json: String): IDKitResult = nativeIdkitResultFromJson(json)

fun hashSignal(signal: Signal): String = hashSignalFfi(signal)

val ProofRequest.credentialIdentifiers: List<String>
get() = proofRequests.map { it.identifier }

val BridgeRequestPayload.credentialIdentifiers: List<String>
get() = proofRequest?.credentialIdentifiers.orEmpty()
111 changes: 111 additions & 0 deletions kotlin/bindings/src/test/kotlin/com/worldcoin/idkit/IDKitTests.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ import uniffi.idkit_core.Preset
import uniffi.idkit_core.ResponseItem
import uniffi.idkit_core.RpContext
import uniffi.idkit_core.StatusWrapper
import uniffi.idkit_core.VerificationLevel
import uniffi.idkit_core.ConstraintKindWrapper
import uniffi.idkit_core.ConstraintNode
import uniffi.idkit_core.CredentialRequest
import uniffi.idkit_core.CredentialType

class IDKitTests {
private fun sampleResult(
Expand Down Expand Up @@ -82,6 +87,112 @@ class IDKitTests {
// IDKit.proveSession("0x01", sessionConfig)
}

@Test
fun `bridge request payload exposes identity check contract fields`() {
val config = IDKitRequestConfig(
appId = "app_staging_1234567890abcdef",
action = "test-action",
rpContext = sampleRpContext(),
actionDescription = "Identity check",
bridgeUrl = null,
allowLegacyProofs = false,
requireUserPresence = true,
overrideConnectBaseUrl = null,
returnTo = "idkitsample://callback",
environment = Environment.STAGING,
connectUrlMode = null,
)

val preset = identityCheck(
attributes = listOf(
IdentityAttribute.MinimumAge(21u),
IdentityAttribute.Nationality("JPN"),
),
)

val payload = IDKit.createBridgePayloadFromPresets(config, preset)

assertEquals("app_staging_1234567890abcdef", payload.appId)
assertEquals("test-action", payload.action)
assertEquals("Identity check", payload.actionDescription)
assertEquals(VerificationLevel.DOCUMENT, payload.verificationLevel)
assertEquals(true, payload.requireUserPresence)
assertEquals(true, payload.allowLegacyProofs)
assertEquals("idkitsample://callback", payload.returnToUrl)
assertEquals(Environment.STAGING, payload.environment)
assertNull(payload.timestamp)

val attributes = payload.identityAttributes!!
assertEquals(
listOf(
IdentityAttribute.MinimumAge(21u),
IdentityAttribute.Nationality("JPN"),
),
attributes,
)

val proofRequest = payload.proofRequest!!
assertEquals(1u, proofRequest.version)
assertEquals("uniqueness", proofRequest.proofType)
assertEquals("rp_1234567890abcdef", proofRequest.rpId)
assertEquals(1_700_000_000u, proofRequest.createdAt)
assertEquals(1_700_003_600u, proofRequest.expiresAt)
assertTrue(proofRequest.id.isNotEmpty())

val constraints = proofRequest.constraints!!
assertEquals(ConstraintKindWrapper.ANY, constraints.kind())
assertEquals(2, constraints.children().size)
assertEquals(ConstraintKindWrapper.TYPE, constraints.children()[0].kind())
assertEquals("passport", constraints.children()[0].identifier())
assertEquals(ConstraintKindWrapper.TYPE, constraints.children()[1].kind())
assertEquals("mnc", constraints.children()[1].identifier())

assertEquals(listOf("passport", "mnc"), proofRequest.credentialIdentifiers)
}

@Test
fun `bridge request payload from constraints exposes passport or mnc`() {
val config = IDKitRequestConfig(
appId = "app_staging_1234567890abcdef",
action = "test-action",
rpContext = sampleRpContext(),
actionDescription = "Identity check",
bridgeUrl = null,
allowLegacyProofs = false,
requireUserPresence = false,
overrideConnectBaseUrl = null,
returnTo = null,
environment = Environment.STAGING,
connectUrlMode = null,
)

val constraints = ConstraintNode.any(
nodes = listOf(
ConstraintNode.item(
request = CredentialRequest.withStringSignal(
credentialType = CredentialType.PASSPORT,
signal = null,
),
),
ConstraintNode.item(
request = CredentialRequest.withStringSignal(
credentialType = CredentialType.MNC,
signal = null,
),
),
),
)

val payload = IDKit.createBridgePayloadFromConstraints(config, constraints)

assertNull(payload.identityAttributes)

val proofRequest = payload.proofRequest!!
val payloadConstraints = proofRequest.constraints!!
assertEquals(ConstraintKindWrapper.ANY, payloadConstraints.kind())
assertEquals(listOf("passport", "mnc"), proofRequest.credentialIdentifiers)
}

@Test
fun `status mapping covers all canonical variants`() {
val result = sampleResult()
Expand Down
Loading
Loading