如何在Corda中编写自定义事件?以token转账通知为例
Alright, let's walk through exactly how to implement custom events in Corda for sending token transfer notifications. I'll break this down into actionable steps with code snippets you can adapt for your use case.
First, you need a serializable event class to carry the notification details. Corda requires event objects to be serializable so they can be passed between nodes or persisted if needed.
import net.corda.core.serialization.CordaSerializable @CordaSerializable data class TokenTransferEvent( val accountId: String, val notificationMessage: String )
This class holds the target account ID and the specific message ("Token is transferred" or "Token is received") we want to send.
Next, you'll trigger these events in your token transfer flow. Whether you're using the Corda Token SDK's built-in flows or a custom transfer flow, you'll emit events after the transfer is confirmed.
Local Account Transfer (Same Node)
If both accounts exist on the same node, you can emit events directly via the node's event service:
import net.corda.core.flows.FlowLogic import net.corda.core.flows.StartableByRPC import net.corda.core.services.eventEvents @StartableByRPC class LocalTokenTransferFlow( private val fromAccountId: String, private val toAccountId: String, private val tokenAmount: Long ) : FlowLogic<Unit>() { override fun call() { // Execute core token transfer logic (e.g., using Token SDK's MoveTokensFlow) // ... your transfer implementation here ... // Emit event for the sending account serviceHub.eventService.emit( TokenTransferEvent(fromAccountId, "Token is transferred") ) // Emit event for the receiving account serviceHub.eventService.emit( TokenTransferEvent(toAccountId, "Token is received") ) } }
Cross-Node Account Transfer
If accounts are on different nodes, you need to pass the event to the receiving node via a flow session. Update your initiator flow to send the event details, then have the responder flow emit the event locally:
Initiator Flow
import net.corda.core.flows.FlowLogic import net.corda.core.flows.StartableByRPC import net.corda.core.identity.Party @StartableByRPC class CrossNodeTokenTransferFlow( private val fromAccountId: String, private val toAccountId: String, private val tokenAmount: Long, private val receivingNode: Party ) : FlowLogic<Unit>() { override fun call() { // Initiate session with the receiving node val session = initiateFlow(receivingNode) // Execute core token transfer logic // ... your cross-node transfer implementation here ... // Emit local event for sending account serviceHub.eventService.emit( TokenTransferEvent(fromAccountId, "Token is transferred") ) // Send event details to receiving node session.send(TokenTransferEvent(toAccountId, "Token is received")) } }
Responder Flow
import net.corda.core.flows.InitiatedBy import net.corda.core.flows.FlowSession import net.corda.core.flows.FlowLogic @InitiatedBy(CrossNodeTokenTransferFlow::class) class CrossNodeTransferResponder(private val otherSession: FlowSession) : FlowLogic<Unit>() { override fun call() { // Receive event from initiator node val transferEvent = otherSession.receive<TokenTransferEvent>().unwrap { it } // Emit event locally for receiving account serviceHub.eventService.emit(transferEvent) } }
Now you need a listener that reacts to the emitted events and sends the actual notifications (e.g., logs, external API calls, emails). Create a class that implements Corda's EventListener:
import net.corda.core.node.services.EventListener import net.corda.core.node.ServiceHub import org.slf4j.LoggerFactory class TokenNotificationListener : EventListener { private val logger = LoggerFactory.getLogger(javaClass) override fun onEvent(event: Any, serviceHub: ServiceHub) { if (event is TokenTransferEvent) { // Implement your notification logic here logger.info("Notification for account ${event.accountId}: ${event.notificationMessage}") // Example: Call an external notification service // externalNotificationService.send(event.accountId, event.notificationMessage) } } }
To activate this listener, register it in your node configuration. Add this to your node.conf file:
eventListeners: - className: com.yourpackage.TokenNotificationListener
You can test this by triggering the transfer flow via RPC and verifying the notifications:
import net.corda.client.rpc.CordaRPCClient import net.corda.core.utilities.NetworkHostAndPort fun main() { val rpcClient = CordaRPCClient(NetworkHostAndPort("localhost", 10006)) val rpcConnection = rpcClient.start("user1", "test") val proxy = rpcConnection.proxy // Trigger cross-node transfer flow proxy.startFlowDynamic( CrossNodeTokenTransferFlow::class.java, "account1", "account2", 500L, proxy.partiesFromName("PartyB", false).single() ).returnValue.get() rpcConnection.close() }
Check your node logs—you should see the notification messages logged for both accounts.
- Always mark event classes with
@CordaSerializableto ensure they work across nodes. - Keep listener logic lightweight to avoid blocking flow execution; use async processing for heavy tasks like external API calls.
- If using the Corda Token SDK, wrap the SDK's
MoveTokensFlowin your custom flow to add event emission logic.
内容的提问来源于stack exchange,提问作者Karan chopra




