corda - CorDapp 在 CRaSH Shell 中工作,但 API 无法识别 CorDapp
问题描述
我正在尝试公开 CorDapp 的 API,但未显示函数。查看示例(https://github.com/roger3cev/obligation-cordapp)时,我收到以下页面:https : //imgur.com/a/ifOdrAd,但是当我加载我的 CorDapp 时,它说有本地主机上没有安装 Cordapps 和 /api 返回 404。在项目中,我觉得问题出在此处:https ://github.com/PronoyC/InsureFlight/tree/master/cordapp/src/main/kotlin/com /保险飞行。我知道这很模糊,但我找不到任何指示特定区域的错误。任何帮助,将不胜感激。
InsureFlightApi.kt:
package com.insureflight
import net.corda.core.contracts.Amount
import net.corda.core.contracts.UniqueIdentifier
import net.corda.core.messaging.CordaRPCOps
import net.corda.core.utilities.OpaqueBytes
import net.corda.core.utilities.getOrThrow
import com.insureflight.flows.IssuePolicy
import com.insureflight.flows.PayoutPolicy
import net.corda.finance.contracts.asset.Cash
import net.corda.finance.contracts.getCashBalances
import net.corda.finance.flows.CashIssueFlow
import java.util.*
import javax.ws.rs.GET
import javax.ws.rs.Path
import javax.ws.rs.Produces
import javax.ws.rs.QueryParam
import javax.ws.rs.core.MediaType
import javax.ws.rs.core.Response
import javax.ws.rs.core.Response.Status.BAD_REQUEST
import javax.ws.rs.core.Response.Status.CREATED
@Path("insureflight")
class InsureFlightApi(val rpcOps: CordaRPCOps) {
private val myIdentity = rpcOps.nodeInfo().legalIdentities.first()
@GET
@Path("me")
@Produces(MediaType.APPLICATION_JSON)
fun me() = mapOf("me" to myIdentity)
@GET
@Path("peers")
@Produces(MediaType.APPLICATION_JSON)
fun peers() = mapOf("peers" to rpcOps.networkMapSnapshot()
.filter { nodeInfo -> nodeInfo.legalIdentities.first() != myIdentity }
.map { it.legalIdentities.first().name.organisation })
@GET
@Path("policies")
@Produces(MediaType.APPLICATION_JSON)
fun policies() = rpcOps.vaultQuery(Policy::class.java).states
@GET
@Path("cash")
@Produces(MediaType.APPLICATION_JSON)
fun cash() = rpcOps.vaultQuery(Cash.State::class.java).states
@GET
@Path("cash-balances")
@Produces(MediaType.APPLICATION_JSON)
fun getCashBalances() = rpcOps.getCashBalances()
@GET
@Path("self-issue-cash")
fun selfIssueCash(@QueryParam(value = "amount") amount: Int,
@QueryParam(value = "currency") currency: String): Response {
// 1. Prepare issue request.
val issueAmount = Amount(amount.toLong(), Currency.getInstance(currency))
val notary = rpcOps.notaryIdentities().firstOrNull() ?: throw IllegalStateException("Could not find a notary.")
val issueRef = OpaqueBytes.of(0)
val issueRequest = CashIssueFlow.IssueRequest(issueAmount, issueRef, notary)
// 2. Start flow and wait for response.
val (status, message) = try {
val flowHandle = rpcOps.startFlowDynamic(CashIssueFlow::class.java, issueRequest)
val result = flowHandle.use { it.returnValue.getOrThrow() }
CREATED to result.stx.tx.outputs.single().data
} catch (e: Exception) {
BAD_REQUEST to e.message
}
// 3. Return the response.
return Response.status(status).entity(message).build()
}
@GET
@Path("issue-policy")
fun issuePolicy(@QueryParam(value = "premium") premium: Int,
@QueryParam(value = "currency") currency: String,
@QueryParam(value = "client") client: String,
@QueryParam(value = "underwriter") underwriter: String,
@QueryParam(value = "flight") flight: String,
@QueryParam(value = "fStatus") fStatus: String): Response {
// 1. Create a premium object.
val issuePremium = Amount(premium.toLong() * 100, Currency.getInstance(currency))
// 2. Start the IssuePolicy flow. We block and wait for the flow to return.
val (status, message) = try {
val flowHandle = rpcOps.startFlowDynamic(
IssuePolicy.Initiator::class.java,
issuePremium,
client,
underwriter,
flight,
fStatus,
true
)
val result = flowHandle.use { it.returnValue.getOrThrow() }
CREATED to "Transaction id ${result.id} committed to ledger.\n${result.tx.outputs.single().data}"
} catch (e: Exception) {
BAD_REQUEST to e.message
}
// 3. Return the result.
return Response.status(status).entity(message).build()
}
@GET
@Path("payout-policy")
fun settlePolicy(@QueryParam(value = "id") id: String,
@QueryParam(value = "delayedMinutes") delayedMinutes: Int,
@QueryParam(value = "fStatus") fStatus: String): Response {
// 1. Get party objects for the counterparty.
val linearId = UniqueIdentifier.fromString(id)
// 2. Start the SettlePolicy flow. We block and wait for the flow to return.
val (status, message) = try {
val flowHandle = rpcOps.startFlowDynamic(
PayoutPolicy.Initiator::class.java,
linearId,
delayedMinutes,
fStatus,
true
)
flowHandle.use { flowHandle.returnValue.getOrThrow() }
CREATED to "Policy $linearId has been settled."
} catch (e: Exception) {
BAD_REQUEST to e.message
}
// 3. Return the result.
return Response.status(status).entity(message).build()
}
}
InsureFlightPlugin.kt(ObligationPlugin.kt 与此非常相似):
package com.insureflight
import net.corda.core.messaging.CordaRPCOps
import net.corda.webserver.services.WebServerPluginRegistry
import java.util.function.Function
class InsureFlightPlugin : WebServerPluginRegistry {
override val webApis: List<Function<CordaRPCOps, out Any>> = listOf(Function(::InsureFlightApi))
override val staticServeDirs: Map<String, String> = mapOf(
"policy" to javaClass.classLoader.getResource("policyWeb").toExternalForm()
)
}
解决方案
Kid101 是正确的。您必须注册 InsureFlightPlugin,如下所示:
推荐阅读
- .net - 使用 IdentityServer 在 .NET API 上找不到控制器路由
- python - 我们如何在热图中绘制来自多索引数据框的数据?
- python - 有人可以解释以下pytorch神经网络中的层代码吗
- python - Python on write time 在 vscode 中显示来自 dict 的建议/提示
- jenkins - 将 jenkins 与 GoCD 集成
- javascript - 如何优化 useReducer 中对象数组的更新?
- python - 'TikTokApi' 对象没有属性'region'
- javascript - 跟进:我有 2 个单选按钮,我想将不同的 ajax 页面加载到 div 元素中,具体取决于选择哪个
- python - 在不使用熊猫的情况下逐行读取后清理文本文件数据
- salesforce - 限制休假用户的访问