-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(agent): Implementation Onboarding invitation on Agent #18
Changes from 8 commits
b81f786
cfe1a42
e576df8
99b0350
7792f13
bf2c421
5e62e75
ee716b0
450e03d
f2d2513
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -71,35 +71,57 @@ kotlin { | |
implementation(project(":domain")) | ||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4") | ||
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.4.1") | ||
|
||
implementation("io.ktor:ktor-client-core:2.1.3") | ||
implementation("io.ktor:ktor-client-content-negotiation:2.1.3") | ||
implementation("io.ktor:ktor-serialization-kotlinx-json:2.1.3") | ||
implementation("io.ktor:ktor-client-logging:2.1.3") | ||
} | ||
} | ||
val commonTest by getting { | ||
dependencies { | ||
implementation(project(":domain")) | ||
implementation(kotlin("test")) | ||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.6.4") | ||
implementation("io.ktor:ktor-client-mock:2.1.3") | ||
} | ||
} | ||
val jvmMain by getting { | ||
dependencies { | ||
implementation("io.ktor:ktor-client-okhttp:2.1.3") | ||
} | ||
} | ||
val jvmMain by getting | ||
val jvmTest by getting { | ||
dependencies { | ||
implementation("junit:junit:4.13.2") | ||
implementation("io.ktor:ktor-client-mock:2.1.3") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Don't need to reimport this one here as you already imported it in 'commonTest' |
||
implementation(kotlin("test")) | ||
} | ||
} | ||
val androidMain by getting { | ||
dependencies { | ||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4") | ||
implementation("io.ktor:ktor-client-okhttp:2.1.3") | ||
} | ||
} | ||
val androidTest by getting { | ||
dependencies { | ||
implementation("junit:junit:4.13.2") | ||
} | ||
} | ||
val jsMain by getting | ||
val jsMain by getting { | ||
dependencies { | ||
implementation("io.ktor:ktor-client-js:2.1.3") | ||
implementation("io.ktor:ktor-client-content-negotiation:2.1.3") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No need to reimport it here as it already was imported in 'commonMain' |
||
implementation("io.ktor:ktor-serialization-kotlinx-json:2.1.3") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No need to reimport it here as it already was imported in 'commonMain' |
||
implementation(npm("abort-controller", "3.0.0")) | ||
implementation(npm("node-fetch", "2.6.7")) | ||
} | ||
} | ||
val jsTest by getting | ||
|
||
all { | ||
languageSettings.optIn("kotlin.js.ExperimentalJsExport") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please don't add this compiler flag. As this will disable so many helpful warnings that are very useful during our development of the JS target |
||
languageSettings.optIn("kotlin.RequiresOptIn") | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package io.iohk.atala.prism.walletsdk.prismagent.helpers | ||
|
||
import io.ktor.client.HttpClientConfig | ||
import io.ktor.client.engine.okhttp.OkHttp | ||
import io.ktor.client.HttpClient as KtorClient | ||
|
||
internal actual fun HttpClient(config: HttpClientConfig<*>.() -> Unit) = KtorClient(OkHttp) { | ||
config(this) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,21 +6,32 @@ import io.iohk.atala.prism.domain.buildingBlocks.Pluto | |
import io.iohk.atala.prism.domain.models.DID | ||
import io.iohk.atala.prism.domain.models.DIDDocument | ||
import io.iohk.atala.prism.domain.models.KeyCurve | ||
import io.iohk.atala.prism.domain.models.PrismAgentError | ||
import io.iohk.atala.prism.domain.models.Seed | ||
import io.iohk.atala.prism.walletsdk.prismagent.helpers.Api | ||
import io.iohk.atala.prism.walletsdk.prismagent.protocols.prismOnboarding.PrismOnboardingInvitation | ||
import io.ktor.http.HttpMethod | ||
import io.ktor.http.Url | ||
import kotlinx.coroutines.flow.first | ||
import kotlinx.coroutines.flow.map | ||
import kotlinx.serialization.Serializable | ||
|
||
final class PrismAgent { | ||
open class PrismAgent { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there a point of this being open ;) I think it should be final. |
||
enum class State { | ||
STOPED, STARTING, RUNNING, STOPING | ||
} | ||
|
||
sealed class InvitationType | ||
|
||
data class PrismOnboardingInvitation(val from: String, val endpoint: String, val ownDID: DID) : InvitationType() | ||
|
||
val seed: Seed | ||
var state = State.STOPED | ||
|
||
private val apollo: Apollo | ||
private val castor: Castor | ||
private val pluto: Pluto | ||
open val api: Api = Api() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think if you really want to make a mocked API. There is a better way than adding this |
||
|
||
constructor( | ||
apollo: Apollo, | ||
|
@@ -72,4 +83,57 @@ final class PrismAgent { | |
|
||
return did | ||
} | ||
|
||
@Throws(PrismAgentError.unknownInvitationTypeError::class) | ||
suspend fun parseInvitation(str: String): InvitationType { | ||
val invite = try { | ||
parsePrismInvitation(str) | ||
} catch (e: Throwable) { | ||
println(e) | ||
throw PrismAgentError.unknownInvitationTypeError() | ||
} | ||
return invite | ||
} | ||
|
||
suspend fun acceptInvitation(invitation: PrismOnboardingInvitation) { | ||
@Serializable | ||
data class SendDID(val did: String) | ||
|
||
var response = api.request( | ||
HttpMethod.Post, | ||
Url(invitation.endpoint), | ||
mapOf(), | ||
mapOf(), | ||
SendDID(invitation.ownDID.toString()) | ||
) | ||
|
||
if (response.status.value != 200) { | ||
throw PrismAgentError.failedToOnboardError() | ||
} | ||
} | ||
|
||
private suspend fun parsePrismInvitation(str: String): PrismOnboardingInvitation { | ||
val prismOnboarding = PrismOnboardingInvitation(str) | ||
val url = prismOnboarding.body.onboardEndpoint | ||
val did = createNewPeerDID( | ||
arrayOf( | ||
DIDDocument.Service( | ||
id = "#didcomm-1", | ||
type = arrayOf("DIDCommMessaging"), | ||
serviceEndpoint = DIDDocument.ServiceEndpoint( | ||
uri = url, | ||
accept = arrayOf("DIDCommMessaging"), | ||
routingKeys = arrayOf() | ||
) | ||
) | ||
), | ||
true | ||
) | ||
|
||
return PrismOnboardingInvitation( | ||
from = prismOnboarding.body.from, | ||
endpoint = url, | ||
ownDID = did | ||
) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
package io.iohk.atala.prism.walletsdk.prismagent.helpers | ||
|
||
import io.ktor.client.plugins.contentnegotiation.ContentNegotiation | ||
import io.ktor.client.request.prepareRequest | ||
import io.ktor.client.request.setBody | ||
import io.ktor.client.statement.HttpResponse | ||
import io.ktor.client.statement.HttpStatement | ||
import io.ktor.http.ContentType | ||
import io.ktor.http.HttpHeaders | ||
import io.ktor.http.HttpMethod | ||
import io.ktor.http.Url | ||
import io.ktor.http.contentType | ||
import io.ktor.http.path | ||
import io.ktor.serialization.kotlinx.json.json | ||
import kotlinx.coroutines.DelicateCoroutinesApi | ||
import kotlinx.serialization.json.Json | ||
import io.ktor.client.HttpClient as KtorClient | ||
|
||
@DelicateCoroutinesApi | ||
open class Api( | ||
private val client: KtorClient = HttpClient { | ||
install(ContentNegotiation) { | ||
json( | ||
Json { | ||
ignoreUnknownKeys = true | ||
prettyPrint = true | ||
isLenient = true | ||
} | ||
) | ||
} | ||
} | ||
) { | ||
|
||
private suspend fun prepareRequest( | ||
httpMethod: HttpMethod, | ||
url: Url, | ||
urlParameters: Map<String, String> = mapOf(), | ||
httpHeaders: Map<String, String> = mapOf(), | ||
body: Any? = null | ||
): HttpStatement { | ||
|
||
return client.prepareRequest { | ||
for (header in httpHeaders) { | ||
if ( | ||
httpMethod == HttpMethod.Get && | ||
header.key == HttpHeaders.ContentType && | ||
header.value.contains(ContentType.Application.Json.contentSubtype) | ||
) { | ||
continue | ||
} | ||
headers.append(header.key, header.value) | ||
} | ||
|
||
contentType(ContentType.Application.Json) | ||
|
||
body?.let { | ||
setBody(body) | ||
} | ||
|
||
url { | ||
method = httpMethod | ||
protocol = url.protocol | ||
host = url.host | ||
port = url.specifiedPort | ||
|
||
path(url.encodedPath) | ||
|
||
for (parameter in urlParameters) { | ||
parameters.append(parameter.key, parameter.value) | ||
} | ||
} | ||
} | ||
} | ||
|
||
suspend fun request( | ||
httpMethod: HttpMethod, | ||
url: Url, | ||
urlParameters: Map<String, String> = mapOf(), | ||
httpHeaders: Map<String, String> = mapOf(), | ||
body: Any? = null | ||
): HttpResponse { | ||
return prepareRequest(httpMethod, url, urlParameters, httpHeaders, body).execute() | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package io.iohk.atala.prism.walletsdk.prismagent.helpers | ||
|
||
import io.ktor.client.HttpClientConfig | ||
import io.ktor.client.HttpClient as KtorClient | ||
|
||
internal expect fun HttpClient(config: HttpClientConfig<*>.() -> Unit = {}): KtorClient |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package io.iohk.atala.prism.walletsdk.prismagent.protocols.prismOnboarding | ||
|
||
import io.iohk.atala.prism.domain.models.PrismAgentError | ||
import kotlinx.serialization.Serializable | ||
import kotlinx.serialization.decodeFromString | ||
import kotlinx.serialization.json.Json | ||
|
||
class PrismOnboardingInvitation(jsonString: String) { | ||
|
||
@Serializable | ||
data class Body( | ||
val type: String, | ||
val onboardEndpoint: String, | ||
val from: String | ||
) | ||
|
||
var body: Body | ||
|
||
init { | ||
val json = Json { | ||
ignoreUnknownKeys = true | ||
prettyPrint = true | ||
isLenient = true | ||
} | ||
body = try { | ||
json.decodeFromString(jsonString) | ||
} catch (e: Throwable) { | ||
throw PrismAgentError.invitationIsInvalidError() | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package io.iohk.atala.prism.walletsdk.prismagent | ||
|
||
import io.iohk.atala.prism.walletsdk.prismagent.helpers.Api | ||
import io.ktor.http.HttpStatusCode | ||
|
||
class AgentApiMock( | ||
statusCode: HttpStatusCode, | ||
response: String | ||
) : PrismAgent(ApolloMock(), CastorMock(), PlutoMock()) { | ||
override val api: Api = ApiMock(statusCode, response) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package io.iohk.atala.prism.walletsdk.prismagent | ||
|
||
import io.iohk.atala.prism.walletsdk.prismagent.helpers.Api | ||
import io.ktor.client.engine.mock.MockEngine | ||
import io.ktor.client.engine.mock.respond | ||
import io.ktor.client.plugins.contentnegotiation.ContentNegotiation | ||
import io.ktor.http.HttpHeaders | ||
import io.ktor.http.HttpStatusCode | ||
import io.ktor.http.headersOf | ||
import io.ktor.serialization.kotlinx.json.json | ||
import kotlinx.coroutines.DelicateCoroutinesApi | ||
import kotlinx.serialization.json.Json | ||
import io.ktor.client.HttpClient as KtorClient | ||
|
||
@OptIn(DelicateCoroutinesApi::class) | ||
class ApiMock : Api { | ||
|
||
constructor(statusCode: HttpStatusCode, response: String) : super( | ||
KtorClient( | ||
engine = MockEngine { _ -> | ||
respond( | ||
content = response, | ||
status = statusCode, | ||
headers = headersOf(HttpHeaders.ContentType, "application/json") | ||
) | ||
} | ||
) { | ||
install(ContentNegotiation) { | ||
json( | ||
Json { | ||
ignoreUnknownKeys = true | ||
prettyPrint = true | ||
isLenient = true | ||
} | ||
) | ||
} | ||
} | ||
) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wrong package name here