Skip to content
This repository has been archived by the owner on Dec 12, 2024. It is now read-only.

Kotlin validate submission pex #1234

Merged
merged 8 commits into from
Feb 14, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ import getLoanAppPresentationDefinitionKt from '!!raw-loader!@site/snippets/test
import satisfiesPresentationDefinitionForPexKt from '!!raw-loader!@site/snippets/testsuite-kotlin/src/test/kotlin/docs/web5/build/verifiablecredentials/satisfiesPresentationDefinitionForPexKt.snippet.kt'
import selectCredentialsForPexKt from '!!raw-loader!@site/snippets/testsuite-kotlin/src/test/kotlin/docs/web5/build/verifiablecredentials/selectCredentialsForPexKt.snippet.kt'
import createPresentationFromCredentialsForPexKt from '!!raw-loader!@site/snippets/testsuite-kotlin/src/test/kotlin/docs/web5/build/verifiablecredentials/createPresentationFromCredentialsForPexKt.snippet.kt'
import validVerifiablePresentationForPexKt from '!!raw-loader!@site/snippets/testsuite-kotlin/src/test/kotlin/docs/web5/build/verifiablecredentials/validVerifiablePresentationForPexKt.snippet.kt'
import validatePresentationSubmissionForPexKt from '!!raw-loader!@site/snippets/testsuite-kotlin/src/test/kotlin/docs/web5/build/verifiablecredentials/validatePresentationSubmissionForPexKt.snippet.kt'
import signVpForPexKt from '!!raw-loader!@site/snippets/testsuite-kotlin/src/test/kotlin/docs/web5/build/verifiablecredentials/signVpForPexKt.snippet.kt'

<LanguageSwitcher languages="JavaScript, Kotlin" />

Expand Down Expand Up @@ -71,6 +72,7 @@ import { PresentationExchange } from '@web5/credentials';
code: `
import web5.sdk.credentials.PresentationExchange
import web5.sdk.credentials.VerifiablePresentation
import web5.sdk.credentials.model.PresentationSubmission
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know I already included import web5.sdk.credentials.model.*, but for some strange reason that doesn't import PresentationSubmission, so that needs to be imported separately.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nitro-neal any thoughts or advice on why I have to import web5.sdk.credentials.model.PresentationSubmission if I'm doing import web5.sdk.credentials.model.*

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is pretty strange, could be ide or linter problem.

Does PresentationDefinition work with *?

Its probably better to import them individually instead of using * to be more explicit and not import unnecessary things, but yea is strange. I'll see if it happens on my end

import web5.sdk.credentials.model.*
`,
language: 'Kotlin',
Expand Down Expand Up @@ -110,8 +112,13 @@ Once you've confirmed that the VCs successfully satisfy the Presentation Definit

<Shnip
snippets={[
{ snippetContent: createPresentationFromCredentialsForPex, language: 'JavaScript'},
{ snippetContent: createPresentationFromCredentialsForPexKt, language: 'Kotlin'},
{
snippetContent: createPresentationFromCredentialsForPex,
language: 'JavaScript'
},
{
snippetContent: createPresentationFromCredentialsForPexKt,
language: 'Kotlin'},
]}
/>

Expand Down Expand Up @@ -215,35 +222,53 @@ Before submitting the presentation to a lender, you can validate the Presentatio
<Shnip
snippets={[
{ snippetContent: validPresentationSubmissionForPex, language: 'JavaScript'},
{ snippetContent: validatePresentationSubmissionForPexKt, language: 'Kotlin'}
]}
inlineSnippets={[
/>

:::note
The information regarding `Checked` objects is only applicable to the JavaScript SDK.
:::


<Shnip
inlineSnippets={[
{
content: 'This functionality is soon to be implemented in the Kotlin SDK.' ,
content: 'This method checks the presentation submission for any errors, returns an array of `Checked` objects representing the validation checks performed on the presentation submission:',
code: `
[ Checked { tag: 'root', status: 'info', message: 'ok' } ]
`,
language: 'JavaScript',
},
{
content: "If unsuccessful, an error will be thrown. Here is an example:",
code:`
PresentationSubmission id must not be empty
`,
language: 'Kotlin',
}
]}
/>

This method checks the presentation submission for any errors, returns an array of `Checked` objects representing the validation checks performed on the presentation submission:

```js
[ Checked { tag: 'root', status: 'info', message: 'ok' } ]
```

Each `Checked` object contains:

- **tag**: the path, `root` of the submission that was checked
- **status**: the result of the check, which is `info` for successful checks or `error` for failed checks
- **message**: shows `ok` if successful, and if unsuccessful this is where you'll find error messages

## Verifiable Presentation


## Verifiable Presentation

<Shnip
snippets={[
{ content: 'Once the [Presentation](/docs/glossary#verifiable-presentation) is error-free and has passed the validation checks, you can submit the Verifiable Presentation by providing the lender with the `presentation` JSON object:', snippetContent: validVerifiablePresentationForPex, language: 'JavaScript'},
{ content: 'After successfully creating the [Presentation](/docs/glossary#verifiable-presentation) using `VerifiablePresentation.create()`, and ensuring it is error-free and has passed all validation checks, you can submit the Verifiable Presentation by providing the lender with the `mappedPresentationSubmission` object:', snippetContent: validVerifiablePresentationForPexKt, language: 'Kotlin'},
{
content: 'Once the [Presentation](/docs/glossary#verifiable-presentation) is error-free and has passed the validation checks, you can submit the Verifiable Presentation by providing the lender with the `presentation` JSON object:',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For JS, why aren't we signing and returning the JWT like we're doing in Kotlin?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that's not available yet. I'm still waiting for that to be merged then released decentralized-identity/web5-js#382

snippetContent:
validVerifiablePresentationForPex, language: 'JavaScript'},
{
content: 'Once the [Presentation](/docs/glossary#verifiable-presentation) is error-free and has passed the validation checks, you can submit the Verifiable Presentation as a signed and encoded JWT to the lender for [verification](/docs/web5/build/verifiable-credentials/verify-vc#verify-verifiable-presentations).',
snippetContent: signVpForPexKt,
language: 'Kotlin'},
]}
/>

/>
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package website.tbd.developer.site.docs.web5.build.decentralizedidentifiers;
package website.tbd.developer.site.docs.web5.build.verifiablecredentials;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.Assertions.*
import web5.sdk.crypto.InMemoryKeyManager
import web5.sdk.dids.methods.dht.DidDht
import web5.sdk.credentials.PresentationExchange
import web5.sdk.credentials.VerifiableCredential
import web5.sdk.credentials.VerifiablePresentation
import web5.sdk.credentials.model.PresentationSubmission
import web5.sdk.credentials.model.*

/**
Expand Down Expand Up @@ -121,47 +123,44 @@ internal class PresentationExchangeTest {
// :snippet-end:
}
}

@Test
fun `createPresentationFromCredentialsForPexKt creates a presentation result`() {
val holderDid = "did:key:zQ3shXrAnbgfytQYQjifUm2EcBBbRAeAeGfgC4TZrjw4X71iZ"
val selectedCredentials = allCredentials
// :snippet-start: createPresentationFromCredentialsForPexKt
val presentationResult = PresentationExchange.createPresentationFromCredentials(
vcJwts = selectedCredentials,
presentationDefinition = presentationDefinition
)

val verifiablePresentation = VerifiablePresentation.create(
vcJwts = selectedCredentials,
holder = holderDid,
additionalData = mapOf("presentation_submission" to presentationResult)
)
// :snippet-end:
assertNotNull(verifiablePresentation, "Verifiable Presentation should not be null")
assertEquals(holderDid, verifiablePresentation.holder, "Holder DID should match")
}

@Test
fun `validVerifiablePresentationForPexKt creates a valid VP`() {
val holderDid = "did:key:zQ3shXrAnbgfytQYQjifUm2EcBBbRAeAeGfgC4TZrjw4X71iZ"
fun `createPresentationForPexKt creates a presentation result, a valid VP, and validates submission`() {
val holderDid = DidDht.create(InMemoryKeyManager())
val selectedCredentials = allCredentials
// :snippet-start: createPresentationFromCredentialsForPexKt
val presentationResult = PresentationExchange.createPresentationFromCredentials(
vcJwts = selectedCredentials,
presentationDefinition = presentationDefinition
)

val verifiablePresentation = VerifiablePresentation.create(
vcJwts = selectedCredentials,
holder = holderDid,
holder = holderDid.uri,
additionalData = mapOf("presentation_submission" to presentationResult)
)
// :snippet-start: validVerifiablePresentationForPexKt
val verifiablePresentationDataModelMap = verifiablePresentation.vpDataModel.toMap()
val mappedPresentationSubmission = verifiablePresentationDataModelMap["presentation_submission"] as? PresentationSubmission
// :snippet-end:
assertDoesNotThrow {
// :snippet-start: validatePresentationSubmissionForPexKt
val vpDataMap = verifiablePresentation.vpDataModel.toMap()
val presentationSubmission = vpDataMap["presentation_submission"] as PresentationSubmission

try {
PresentationExchange.validateSubmission(presentationSubmission)
} catch (e: Exception) {
println("Invalid Presentation Submission: ${e.message}")
}
// :snippet-end:
}

// :snippet-start: signVpForPexKt
val vpJwt = verifiablePresentation.sign(holderDid)
// :snippet-end:

assertNotNull(mappedPresentationSubmission, "Mapped Presentation Submission should not be null")
assertEquals(presentationResult.definitionId, mappedPresentationSubmission?.definitionId, "Definition ID should match")
assertNotNull(verifiablePresentation, "Verifiable Presentation should not be null")
assertEquals(holderDid.uri, verifiablePresentation.holder, "Holder DID should match")
assertNotNull(vpJwt, "Verifiable Presentation JWT should not be null")
assertTrue(vpJwt is String, "Verifiable Presentation JWT should be a string")
}
}

Expand Down
Loading