-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #75 from lightsparkdev/feat/demosigner
Add a demo remote signing server
- Loading branch information
Showing
14 changed files
with
326 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
.gradle | ||
build/ | ||
!gradle/wrapper/gradle-wrapper.jar | ||
!**/src/main/**/build/ | ||
!**/src/test/**/build/ | ||
|
||
### STS ### | ||
.apt_generated | ||
.classpath | ||
.factorypath | ||
.project | ||
.settings | ||
.springBeans | ||
.sts4-cache | ||
bin/ | ||
!**/src/main/**/bin/ | ||
!**/src/test/**/bin/ | ||
|
||
### IntelliJ IDEA ### | ||
.idea | ||
*.iws | ||
*.iml | ||
*.ipr | ||
out/ | ||
!**/src/main/**/out/ | ||
!**/src/test/**/out/ | ||
|
||
### NetBeans ### | ||
/nbproject/private/ | ||
/nbbuild/ | ||
/dist/ | ||
/nbdist/ | ||
/.nb-gradle/ | ||
|
||
### VS Code ### | ||
.vscode/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
plugins { | ||
kotlin("jvm") | ||
id("io.ktor.plugin") version "2.3.3" | ||
alias(libs.plugins.kotlinSerialization) | ||
} | ||
|
||
group = "com.lightspark" | ||
version = "0.0.1" | ||
|
||
task("prepareKotlinIdeaImport") {} | ||
task("prepareKotlinBuildScriptModel") {} | ||
|
||
application { | ||
mainClass.set("com.lightspark.ApplicationKt") | ||
|
||
val isDevelopment: Boolean = project.ext.has("development") | ||
applicationDefaultJvmArgs = listOf("-Dio.ktor.development=$isDevelopment") | ||
} | ||
|
||
dependencies { | ||
implementation("io.ktor:ktor-server-core-jvm") | ||
implementation("io.ktor:ktor-server-default-headers-jvm") | ||
implementation("io.ktor:ktor-server-call-logging-jvm") | ||
implementation("io.ktor:ktor-server-content-negotiation-jvm") | ||
implementation("io.ktor:ktor-client-content-negotiation-jvm") | ||
implementation("io.ktor:ktor-serialization-kotlinx-json-jvm") | ||
implementation("io.ktor:ktor-server-auth-jvm") | ||
implementation("io.ktor:ktor-server-compression-jvm") | ||
implementation("io.ktor:ktor-server-netty-jvm") | ||
implementation(project(":lightspark-sdk")) | ||
implementation(project(":core")) | ||
implementation(project(":crypto")) | ||
implementation("ch.qos.logback:logback-classic:1.4.11") | ||
testImplementation("io.ktor:ktor-server-tests-jvm") | ||
testImplementation(libs.kotlin.test.junit) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
kotlin.code.style=official |
21 changes: 21 additions & 0 deletions
21
remotesignerdemo/src/main/kotlin/com/lightspark/Application.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package com.lightspark | ||
|
||
import com.lightspark.plugins.configureHTTP | ||
import com.lightspark.plugins.configureMonitoring | ||
import com.lightspark.plugins.configureRouting | ||
import io.ktor.server.application.Application | ||
import io.ktor.server.engine.embeddedServer | ||
import io.ktor.server.netty.Netty | ||
|
||
fun main() { | ||
val port = System.getenv("PORT")?.toInt() ?: 8080 | ||
embeddedServer(Netty, port = port, host = "0.0.0.0", module = Application::module) | ||
.start(wait = true) | ||
} | ||
|
||
fun Application.module() { | ||
val config = RemoteSigningConfig.fromEnv() | ||
configureHTTP() | ||
configureMonitoring() | ||
configureRouting(config) | ||
} |
11 changes: 11 additions & 0 deletions
11
remotesignerdemo/src/main/kotlin/com/lightspark/Logging.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package com.lightspark | ||
|
||
import io.ktor.server.application.ApplicationCall | ||
|
||
fun ApplicationCall.debugLog(message: String) { | ||
application.environment.log.debug(message) | ||
} | ||
|
||
fun ApplicationCall.errorLog(message: String, exception: Throwable? = null) { | ||
application.environment.log.error(message, exception) | ||
} |
30 changes: 30 additions & 0 deletions
30
remotesignerdemo/src/main/kotlin/com/lightspark/RemoteSigningConfig.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
@file:OptIn(ExperimentalStdlibApi::class) | ||
|
||
package com.lightspark | ||
|
||
data class RemoteSigningConfig( | ||
val apiClientID: String, | ||
val apiClientSecret: String, | ||
val webhookSecret: String, | ||
val masterSeedHex: String, | ||
val clientBaseURL: String?, | ||
) { | ||
val masterSeed: ByteArray | ||
get() = masterSeedHex.hexToByteArray() | ||
|
||
companion object { | ||
fun fromEnv(): RemoteSigningConfig { | ||
return RemoteSigningConfig( | ||
apiClientID = System.getenv("LIGHTSPARK_API_TOKEN_CLIENT_ID") | ||
?: error("LIGHTSPARK_API_TOKEN_CLIENT_ID not set"), | ||
apiClientSecret = System.getenv("LIGHTSPARK_API_TOKEN_CLIENT_SECRET") | ||
?: error("LIGHTSPARK_API_TOKEN_CLIENT_SECRET not set"), | ||
webhookSecret = System.getenv("LIGHTSPARK_WEBHOOK_SECRET") | ||
?: error("LIGHTSPARK_WEBHOOK_SECRET not set"), | ||
masterSeedHex = System.getenv("LIGHTSPARK_MASTER_SEED_HEX") | ||
?: error("LIGHTSPARK_MASTER_SEED_HEX not set"), | ||
clientBaseURL = System.getenv("LIGHTSPARK_EXAMPLE_BASE_URL"), | ||
) | ||
} | ||
} | ||
} |
47 changes: 47 additions & 0 deletions
47
remotesignerdemo/src/main/kotlin/com/lightspark/WebhookHandler.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
package com.lightspark | ||
|
||
import com.lightspark.sdk.LightsparkCoroutinesClient | ||
import com.lightspark.sdk.model.WebhookEventType | ||
import com.lightspark.sdk.remotesigning.handleRemoteSigningEvent | ||
import com.lightspark.sdk.uma.PubKeyResponse | ||
import com.lightspark.sdk.webhooks.SIGNATURE_HEADER | ||
import com.lightspark.sdk.webhooks.verifyAndParseWebhook | ||
import io.ktor.http.HttpStatusCode | ||
import io.ktor.server.application.ApplicationCall | ||
import io.ktor.server.request.receiveText | ||
import io.ktor.server.response.respond | ||
|
||
suspend fun handleWebhookRequest( | ||
call: ApplicationCall, | ||
config: RemoteSigningConfig, | ||
client: LightsparkCoroutinesClient | ||
): String { | ||
val signature = call.request.headers[SIGNATURE_HEADER] ?: run { | ||
call.respond(HttpStatusCode.BadRequest, "Missing signature header.") | ||
return "Missing signature header." | ||
} | ||
val webhookEvent = try { | ||
val bodyBytes = call.receiveText().toByteArray() | ||
verifyAndParseWebhook(bodyBytes, signature, config.webhookSecret) | ||
} catch (e: Exception) { | ||
call.respond(HttpStatusCode.BadRequest, "Invalid webhook request.") | ||
return "Invalid webhook request or bad signature." | ||
} | ||
|
||
val response = when (webhookEvent.eventType) { | ||
WebhookEventType.REMOTE_SIGNING -> try { | ||
handleRemoteSigningEvent(client, webhookEvent, config.masterSeed) | ||
} catch (e: Exception) { | ||
call.respond(HttpStatusCode.InternalServerError, "Error handling remote signing event.") | ||
return "Error handling remote signing event." | ||
} | ||
else -> { | ||
call.respond(HttpStatusCode.OK) | ||
return "Unhandled webhook event type ${webhookEvent.eventType}." | ||
} | ||
} | ||
|
||
call.respond(HttpStatusCode.OK) | ||
|
||
return response | ||
} |
35 changes: 35 additions & 0 deletions
35
remotesignerdemo/src/main/kotlin/com/lightspark/plugins/HTTP.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package com.lightspark.plugins | ||
|
||
import io.ktor.serialization.kotlinx.json.json | ||
import io.ktor.server.application.Application | ||
import io.ktor.server.application.install | ||
import io.ktor.server.plugins.compression.Compression | ||
import io.ktor.server.plugins.compression.deflate | ||
import io.ktor.server.plugins.compression.gzip | ||
import io.ktor.server.plugins.compression.minimumSize | ||
import io.ktor.server.plugins.contentnegotiation.ContentNegotiation | ||
import io.ktor.server.plugins.defaultheaders.DefaultHeaders | ||
import kotlinx.serialization.json.Json | ||
|
||
fun Application.configureHTTP() { | ||
install(DefaultHeaders) { | ||
header("X-Engine", "Ktor") // will send this header with each response | ||
} | ||
install(ContentNegotiation) { | ||
json( | ||
Json { | ||
prettyPrint = true | ||
isLenient = true | ||
}, | ||
) | ||
} | ||
install(Compression) { | ||
gzip { | ||
priority = 1.0 | ||
} | ||
deflate { | ||
priority = 10.0 | ||
minimumSize(1024) // condition | ||
} | ||
} | ||
} |
13 changes: 13 additions & 0 deletions
13
remotesignerdemo/src/main/kotlin/com/lightspark/plugins/Monitoring.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package com.lightspark.plugins | ||
|
||
import io.ktor.server.application.* | ||
import io.ktor.server.plugins.callloging.* | ||
import io.ktor.server.request.* | ||
import org.slf4j.event.* | ||
|
||
fun Application.configureMonitoring() { | ||
install(CallLogging) { | ||
level = Level.INFO | ||
filter { call -> call.request.path().startsWith("/") } | ||
} | ||
} |
35 changes: 35 additions & 0 deletions
35
remotesignerdemo/src/main/kotlin/com/lightspark/plugins/Routing.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package com.lightspark.plugins | ||
|
||
import com.lightspark.RemoteSigningConfig | ||
import com.lightspark.debugLog | ||
import com.lightspark.handleWebhookRequest | ||
import com.lightspark.sdk.ClientConfig | ||
import com.lightspark.sdk.LightsparkCoroutinesClient | ||
import com.lightspark.sdk.auth.AccountApiTokenAuthProvider | ||
import io.ktor.http.HttpStatusCode | ||
import io.ktor.server.application.Application | ||
import io.ktor.server.application.call | ||
import io.ktor.server.response.respond | ||
import io.ktor.server.routing.get | ||
import io.ktor.server.routing.routing | ||
|
||
fun Application.configureRouting( | ||
config: RemoteSigningConfig, | ||
client: LightsparkCoroutinesClient = LightsparkCoroutinesClient( | ||
ClientConfig( | ||
serverUrl = config.clientBaseURL ?: "api.lightspark.com", | ||
authProvider = AccountApiTokenAuthProvider(config.apiClientID, config.apiClientSecret), | ||
), | ||
), | ||
) { | ||
routing { | ||
get("/ping") { | ||
call.respond(HttpStatusCode.NoContent) | ||
} | ||
|
||
get("/ln/webhooks") { | ||
val response = handleWebhookRequest(call, config, client) | ||
call.debugLog("Handled webhook event: $response") | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
<configuration> | ||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> | ||
<encoder> | ||
<pattern>%d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern> | ||
</encoder> | ||
</appender> | ||
<root level="trace"> | ||
<appender-ref ref="STDOUT"/> | ||
</root> | ||
<logger name="org.eclipse.jetty" level="INFO"/> | ||
<logger name="io.netty" level="INFO"/> | ||
</configuration> |
46 changes: 46 additions & 0 deletions
46
remotesignerdemo/src/test/kotlin/com/lightspark/ApplicationTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
package com.lightspark | ||
|
||
import com.lightspark.plugins.configureHTTP | ||
import com.lightspark.plugins.configureRouting | ||
import com.lightspark.sdk.crypto.Secp256k1 | ||
import com.lightspark.sdk.uma.InMemoryPublicKeyCache | ||
import com.lightspark.sdk.uma.KtorUmaRequester | ||
import com.lightspark.sdk.uma.KycStatus | ||
import com.lightspark.sdk.uma.LnurlpResponse | ||
import com.lightspark.sdk.uma.PayReqResponse | ||
import com.lightspark.sdk.uma.UMA_VERSION_STRING | ||
import com.lightspark.sdk.uma.UmaProtocolHelper | ||
import io.ktor.client.call.body | ||
import io.ktor.client.plugins.contentnegotiation.ContentNegotiation | ||
import io.ktor.client.request.get | ||
import io.ktor.client.request.post | ||
import io.ktor.client.request.setBody | ||
import io.ktor.http.HttpStatusCode | ||
import io.ktor.http.contentType | ||
import io.ktor.serialization.kotlinx.json.json | ||
import io.ktor.server.testing.testApplication | ||
import kotlin.test.Test | ||
import kotlin.test.assertEquals | ||
import kotlin.test.assertNotNull | ||
import kotlin.test.assertTrue | ||
|
||
@OptIn(ExperimentalStdlibApi::class) | ||
class ApplicationTest { | ||
val env = RemoteSigningConfig.fromEnv() | ||
|
||
@Test | ||
fun testPingRequest() = testApplication { | ||
val client = createClient { | ||
install(ContentNegotiation) { | ||
json() | ||
} | ||
} | ||
application { | ||
configureHTTP() | ||
configureRouting(env) | ||
} | ||
client.get("/ping").apply { | ||
assertEquals(HttpStatusCode.NoContent, status) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters