diff --git a/example/src/main/java/com/spruceid/mobilesdkexample/wallet/HandleOID4VCIView.kt b/example/src/main/java/com/spruceid/mobilesdkexample/wallet/HandleOID4VCIView.kt index 3d164c1..f4a1b56 100644 --- a/example/src/main/java/com/spruceid/mobilesdkexample/wallet/HandleOID4VCIView.kt +++ b/example/src/main/java/com/spruceid/mobilesdkexample/wallet/HandleOID4VCIView.kt @@ -34,47 +34,51 @@ import io.ktor.util.toMap @Composable fun HandleOID4VCIView( - navController: NavHostController, - url: String, - credentialPacksViewModel: CredentialPacksViewModel + navController: NavHostController, + url: String, + credentialPacksViewModel: CredentialPacksViewModel ) { - var loading by remember { - mutableStateOf(false) - } - var err by remember { - mutableStateOf(null) - } - var credential by remember { - mutableStateOf(null) - } + var loading by remember { mutableStateOf(false) } + var err by remember { mutableStateOf(null) } + var credential by remember { mutableStateOf(null) } val ctx = LocalContext.current LaunchedEffect(Unit) { loading = true val client = HttpClient(CIO) - val oid4vciSession = Oid4vci.newWithAsyncClient(client = object : AsyncHttpClient { - override suspend fun httpClient(request: HttpRequest): HttpResponse { - val res = client.request(request.url) { - method = HttpMethod(request.method) - for ((k, v) in request.headers) { - headers[k] = v - } - setBody(request.body) - } - - return HttpResponse( - statusCode = res.status.value.toUShort(), - headers = res.headers.toMap().mapValues { it.value.joinToString() }, - body = res.readBytes() + val oid4vciSession = + Oid4vci.newWithAsyncClient( + client = + object : AsyncHttpClient { + override suspend fun httpClient( + request: HttpRequest + ): HttpResponse { + val res = + client.request(request.url) { + method = HttpMethod(request.method) + for ((k, v) in request.headers) { + headers[k] = v + } + setBody(request.body) + } + + return HttpResponse( + statusCode = res.status.value.toUShort(), + headers = + res.headers.toMap().mapValues { + it.value.joinToString() + }, + body = res.readBytes() + ) + } + } ) - } - }) try { oid4vciSession.initiateWithOffer( - credentialOffer = url, - clientId = "skit-demo-wallet", - redirectUrl = "https://spruceid.com" + credentialOffer = url, + clientId = "skit-demo-wallet", + redirectUrl = "https://spruceid.com" ) val nonce = oid4vciSession.exchangeToken() @@ -85,47 +89,49 @@ fun HandleOID4VCIView( keyManager.generateSigningKey(id = "reference-app/default-signing") val jwk = keyManager.getJwk(id = "reference-app/default-signing") - val signingInput = jwk?.let { - generatePopPrepare( - audience = metadata.issuer(), - nonce = nonce, - didMethod = DidMethod.JWK, - publicJwk = jwk, - durationInSecs = null - ) - } + val signingInput = + jwk?.let { + generatePopPrepare( + audience = metadata.issuer(), + nonce = nonce, + didMethod = DidMethod.JWK, + publicJwk = jwk, + durationInSecs = null + ) + } - val signature = signingInput?.let { - keyManager.signPayload( - id = "reference-app/default-signing", - payload = signingInput - ) - } + val signature = + signingInput?.let { + keyManager.signPayload( + id = "reference-app/default-signing", + payload = signingInput + ) + } - val pop = signingInput?.let { - signature?.let { - generatePopComplete( - signingInput = signingInput, - signature = Base64.encodeToString( - signature, - Base64.URL_SAFE - or Base64.NO_PADDING - or Base64.NO_WRAP - ).toByteArray() - ) - } - } + val pop = + signingInput?.let { + signature?.let { + generatePopComplete( + signingInput = signingInput, + signature = + Base64.encodeToString( + signature, + Base64.URL_SAFE or + Base64.NO_PADDING or + Base64.NO_WRAP + ) + .toByteArray() + ) + } + } oid4vciSession.setContextMap(getVCPlaygroundOID4VCIContext(ctx = ctx)) - val credentials = pop?.let { - oid4vciSession.exchangeCredential(proofsOfPossession = listOf(pop)) - } + val credentials = + pop?.let { oid4vciSession.exchangeCredential(proofsOfPossession = listOf(pop)) } credentials?.forEach { cred -> - cred.payload.toString(Charsets.UTF_8).let { - credential = it - } + cred.payload.toString(Charsets.UTF_8).let { credential = it } } } catch (e: Exception) { err = e.localizedMessage @@ -138,82 +144,100 @@ fun HandleOID4VCIView( LoadingView(loadingText = "Loading...") } else if (err != null) { ErrorView( - errorTitle = "Error Adding Credential", - errorDetails = err!!, - onClose = { - navController.navigate(Screen.HomeScreen.route) { - popUpTo(0) - } - } + errorTitle = "Error Adding Credential", + errorDetails = err!!, + onClose = { navController.navigate(Screen.HomeScreen.route) { popUpTo(0) } } ) } else if (credential != null) { AddToWalletView( - navController = navController, - rawCredential = credential!!, - credentialPacksViewModel = credentialPacksViewModel + navController = navController, + rawCredential = credential!!, + credentialPacksViewModel = credentialPacksViewModel ) } } - fun getVCPlaygroundOID4VCIContext(ctx: Context): Map { val context = mutableMapOf() context["https://contexts.vcplayground.org/examples/alumni/v1.json"] = - ctx.resources.openRawResource(R.raw.contexts_vcplayground_org_examples_alumni_v1) - .bufferedReader() - .readLines() - .joinToString("") + ctx.resources + .openRawResource(R.raw.contexts_vcplayground_org_examples_alumni_v1) + .bufferedReader() + .readLines() + .joinToString("") context["https://w3id.org/first-responder/v1"] = - ctx.resources.openRawResource(R.raw.w3id_org_first_responder_v1) - .bufferedReader() - .readLines() - .joinToString("") + ctx.resources + .openRawResource(R.raw.w3id_org_first_responder_v1) + .bufferedReader() + .readLines() + .joinToString("") context["https://w3id.org/vdl/aamva/v1"] = - ctx.resources.openRawResource(R.raw.w3id_org_vdl_aamva_v1) - .bufferedReader() - .readLines() - .joinToString("") + ctx.resources + .openRawResource(R.raw.w3id_org_vdl_aamva_v1) + .bufferedReader() + .readLines() + .joinToString("") context["https://w3id.org/citizenship/v3"] = - ctx.resources.openRawResource(R.raw.w3id_org_citizenship_v3) - .bufferedReader() - .readLines() - .joinToString("") + ctx.resources + .openRawResource(R.raw.w3id_org_citizenship_v3) + .bufferedReader() + .readLines() + .joinToString("") context["https://contexts.vcplayground.org/examples/movie-ticket/v1.json"] = - ctx.resources.openRawResource(R.raw.contexts_vcplayground_org_examples_movie_ticket_v1) - .bufferedReader() - .readLines() - .joinToString("") + ctx.resources + .openRawResource(R.raw.contexts_vcplayground_org_examples_movie_ticket_v1) + .bufferedReader() + .readLines() + .joinToString("") context["https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.2.json"] = - ctx.resources.openRawResource(R.raw.purl_imsglobal_org_spec_ob_v3p0_context_3_0_2) - .bufferedReader() - .readLines() - .joinToString("") + ctx.resources + .openRawResource(R.raw.purl_imsglobal_org_spec_ob_v3p0_context_3_0_2) + .bufferedReader() + .readLines() + .joinToString("") context["https://contexts.vcplayground.org/examples/food-safety-certification/v1.json"] = - ctx.resources.openRawResource(R.raw.contexts_vcplayground_org_examples_food_safety_certification_v1) - .bufferedReader() - .readLines() - .joinToString("") + ctx.resources + .openRawResource( + R.raw.contexts_vcplayground_org_examples_food_safety_certification_v1 + ) + .bufferedReader() + .readLines() + .joinToString("") context["https://contexts.vcplayground.org/examples/gs1-8110-coupon/v2.json"] = - ctx.resources.openRawResource(R.raw.contexts_vcplayground_org_examples_gs1_8110_coupon_v2) - .bufferedReader() - .readLines() - .joinToString("") + ctx.resources + .openRawResource(R.raw.contexts_vcplayground_org_examples_gs1_8110_coupon_v2) + .bufferedReader() + .readLines() + .joinToString("") context["https://contexts.vcplayground.org/examples/customer-loyalty/v1.json"] = - ctx.resources.openRawResource(R.raw.contexts_vcplayground_org_examples_customer_loyalty_v1) - .bufferedReader() - .readLines() - .joinToString("") + ctx.resources + .openRawResource(R.raw.contexts_vcplayground_org_examples_customer_loyalty_v1) + .bufferedReader() + .readLines() + .joinToString("") + + context["https://w3id.org/citizenship/v4rc1"] = + ctx.resources + .openRawResource(R.raw.w3id_org_citizenship_v4rc1) + .bufferedReader() + .readLines() + .joinToString("") + + context["https://w3id.org/vc/render-method/v2rc1"] = + ctx.resources + .openRawResource(R.raw.w3id_org_vc_render_method_v2rc1) + .bufferedReader() + .readLines() + .joinToString("") return context } - - diff --git a/example/src/main/res/raw/w3id_org_citizenship_v4rc1.json b/example/src/main/res/raw/w3id_org_citizenship_v4rc1.json new file mode 100644 index 0000000..94cd39b --- /dev/null +++ b/example/src/main/res/raw/w3id_org_citizenship_v4rc1.json @@ -0,0 +1,254 @@ +{ + "@context": { + "@protected": true, + + "image": { "@id": "https://schema.org/image", "@type": "@id" }, + + "QuantitativeValue": { + "@id": "https://schema.org/QuantitativeValue", + "@context": { + "@protected": true, + + "unitCode": "https://schema.org/unitCode", + "value": "https://schema.org/value" + } + }, + + "PostalAddress": { + "@id": "https://schema.org/PostalAddress", + "@context": { + "@protected": true, + + "addressCountry": "https://schema.org/addressCountry", + "addressLocality": "https://schema.org/addressLocality", + "addressRegion": "https://schema.org/addressRegion" + } + }, + + "Person": { + "@id": "https://schema.org/Person", + + "@context": { + "@protected": true, + + "id": "@id", + "type": "@type", + + "additionalName": "https://schema.org/additionalName", + "birthCountry": "https://w3id.org/citizenship#birthCountry", + "birthDate": { + "@id": "https://schema.org/birthDate", + "@type": "http://www.w3.org/2001/XMLSchema#dateTime" + }, + "familyName": "https://schema.org/familyName", + "gender": "https://schema.org/gender", + "givenName": "https://schema.org/givenName", + "height": "https://schema.org/height", + "image": { "@id": "https://schema.org/image", "@type": "@id" }, + "maritalStatus": "https://w3id.org/citizenship#maritalStatus", + "marriageCertificateNumber": "https://w3id.org/citizenship#marriageCertificateNumber", + "marriageLocation": { + "@id": "https://w3id.org/citizenship#marriageLocation", + "@type": "@id" + } + } + }, + + "PermanentResident": { + "@id": "https://w3id.org/citizenship#PermanentResident", + "@context": { + "@protected": true, + + "id": "@id", + "type": "@type", + + "commuterClassification": "https://w3id.org/citizenship#commuterClassification", + "formerNationality": "https://w3id.org/citizenship#formerNationality", + "permanentResidentCard": { + "@id": "https://w3id.org/citizenship#permanentResidentCard", + "@type": "@id" + }, + "residence": { + "@id": "https://w3id.org/citizenship#residence", + "@type": "@id" + }, + "residentSince": { + "@id": "https://w3id.org/citizenship#residentSince", + "@type": "http://www.w3.org/2001/XMLSchema#dateTime" + } + } + }, + + "PermanentResidentCard": { + "@id": "https://w3id.org/citizenship#PermanentResidentCard", + "@context": { + "@protected": true, + + "id": "@id", + "type": "@type", + + "filingLocation": { + "@id": "https://w3id.org/citizenship#filingLocation", + "@type": "@id" + }, + "identifier": "https://schema.org/identifier", + "lprCategory": "https://w3id.org/citizenship#lprCategory", + "lprNumber": "https://w3id.org/citizenship#lprNumber", + "mrzHash": { + "@id": "https://w3id.org/citizenship#mrzHash", + "@type": "https://w3id.org/security#multibase" + } + } + }, + + "PermanentResidentCardCredential": "https://w3id.org/citizenship#PermanentResidentCardCredential", + + "EmployablePerson": { + "@id": "https://w3id.org/citizenship#EmployablePerson", + "@context": { + "@protected": true, + + "id": "@id", + "type": "@type", + + "commuterClassification": "https://w3id.org/citizenship#commuterClassification", + "employmentAuthorizationDocument": { + "@id": "https://w3id.org/citizenship#employmentAuthorizationDocument", + "@type": "@id" + }, + "formerNationality": "https://w3id.org/citizenship#formerNationality", + "residence": { + "@id": "https://w3id.org/citizenship#residence", + "@type": "@id" + }, + "residentSince": { + "@id": "https://w3id.org/citizenship#residentSince", + "@type": "http://www.w3.org/2001/XMLSchema#dateTime" + } + } + }, + + "EmploymentAuthorizationDocument": { + "@id": "https://w3id.org/citizenship#EmploymentAuthorizationDocument", + "@context": { + "@protected": true, + + "id": "@id", + "type": "@type", + + "filingLocation": { + "@id": "https://w3id.org/citizenship#filingLocation", + "@type": "@id" + }, + "identifier": "https://schema.org/identifier", + "lprCategory": "https://w3id.org/citizenship#lprCategory", + "lprNumber": "https://w3id.org/citizenship#lprNumber", + "mrzHash": { + "@id": "https://w3id.org/citizenship#mrzHash", + "@type": "https://w3id.org/security#multibase" + } + } + }, + + "EmploymentAuthorizationDocumentCredential": "https://w3id.org/citizenship#EmploymentAuthorizationDocumentCredential", + + "NaturalizedPerson": { + "@id": "https://w3id.org/citizenship#NaturalizedPerson", + "@context": { + "@protected": true, + + "id": "@id", + "type": "@type", + + "formerNationality": "https://w3id.org/citizenship#formerNationality", + "certificateOfNaturalization": { + "@id": "https://w3id.org/citizenship#certificateOfNaturalization", + "@type": "@id" + }, + "residence": { + "@id": "https://w3id.org/citizenship#residence", + "@type": "@id" + }, + "residentSince": { + "@id": "https://w3id.org/citizenship#residentSince", + "@type": "http://www.w3.org/2001/XMLSchema#dateTime" + }, + "commuterClassification": "https://w3id.org/citizenship#commuterClassification" + } + }, + + "CertificateOfNaturalization": { + "@id": "https://w3id.org/citizenship#CertificateOfNaturalization", + "@context": { + "@protected": true, + + "id": "@id", + "type": "@type", + + "ceremonyDate": { + "@id": "https://w3id.org/citizenship#ceremonyDate", + "@type": "http://www.w3.org/2001/XMLSchema#dateTime" + }, + "ceremonyLocation": { + "@id": "https://w3id.org/citizenship#ceremonyLocation", + "@type": "@id" + }, + "filingLocation": { + "@id": "https://w3id.org/citizenship#filingLocation", + "@type": "@id" + }, + "naturalizationLocation": { + "@id": "https://w3id.org/citizenship#naturalizationLocation", + "@type": "@id" + }, + "naturalizedBy": "https://w3id.org/citizenship#naturalizedBy", + "identifier": "https://schema.org/identifier", + "insRegistrationNumber": "https://w3id.org/citizenship#insRegistrationNumber" + } + }, + + "CertificateOfNaturalizationCredential": "https://w3id.org/citizenship#CertificateOfNaturalizationCredential", + + "Citizen": { + "@id": "https://w3id.org/citizenship#Citizen", + "@context": { + "@protected": true, + + "id": "@id", + "type": "@type", + + "certificateOfCitizenship": { + "@id": "https://w3id.org/citizenship#certificateOfCitizenship", + "@type": "@id" + } + } + }, + + "CertificateOfCitizenship": { + "@id": "https://w3id.org/citizenship#CertificateOfCitizenship", + "@context": { + "@protected": true, + + "id": "@id", + "type": "@type", + + "filingLocation": { + "@id": "https://w3id.org/citizenship#filingLocation", + "@type": "@id" + }, + "identifier": "https://schema.org/identifier", + "ceremonyDate": { + "@id": "https://w3id.org/citizenship#ceremonyDate", + "@type": "http://www.w3.org/2001/XMLSchema#dateTime" + }, + "ceremonyLocation": { + "@id": "https://w3id.org/citizenship#ceremonyLocation", + "@type": "@id" + }, + "cisRegistrationNumber": "https://w3id.org/citizenship#cisRegistrationNumber" + } + }, + + "CertificateOfCitizenshipCredential": "https://w3id.org/citizenship#CertificateOfCitizenshipCredential" + } +} diff --git a/example/src/main/res/raw/w3id_org_vc_render_method_v2rc1 b/example/src/main/res/raw/w3id_org_vc_render_method_v2rc1 new file mode 100644 index 0000000..df725bc --- /dev/null +++ b/example/src/main/res/raw/w3id_org_vc_render_method_v2rc1 @@ -0,0 +1,39 @@ +{ + "@context": { + "@protected": true, + "id": "@id", + "type": "@type", + "SvgRenderingTemplate2023": { + "@id": "https://w3id.org/vc/render-method#SvgRenderingTemplate2023", + "@context": { + "@protected": true, + "id": "@id", + "type": "@type", + "css3MediaQuery": { + "@id": "https://w3id.org/vc/render-method#css3MediaQuery" + }, + "digestMultibase": { + "@id": "https://w3id.org/security#digestMultibase", + "@type": "https://w3id.org/security#multibase" + }, + "name": "https://schema.org/name" + } + }, + "SvgRenderingTemplate2024": { + "@id": "https://w3id.org/vc/render-method#SvgRenderingTemplate2024", + "@context": { + "@protected": true, + "id": "@id", + "type": "@type", + "digestMultibase": { + "@id": "https://w3id.org/security#digestMultibase", + "@type": "https://w3id.org/security#multibase" + }, + "mediaQuery": "https://w3id.org/vc/render-method#mediaQuery", + "mediaType": "https://schema.org/encodingFormat", + "name": "https://schema.org/name", + "template": "https://w3id.org/vc/render-method#template" + } + } + } +}