mirror of
https://github.com/corda/corda.git
synced 2025-01-24 05:18:24 +00:00
parent
d0daac8dd6
commit
21e1c86155
21
.idea/runConfigurations/CordaPlugin.xml
generated
Normal file
21
.idea/runConfigurations/CordaPlugin.xml
generated
Normal file
@ -0,0 +1,21 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="CordaPlugin" type="GradleRunConfiguration" factoryName="Gradle" singleton="true">
|
||||
<log_file path="$PROJECT_DIR$/experimental/intellij-plugin/build/idea-sandbox/system/log/idea.log" checked="true" skipped="true" show_all="false" alias="idea.log" />
|
||||
<ExternalSystemSettings>
|
||||
<option name="executionName" />
|
||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||
<option name="externalSystemIdString" value="GRADLE" />
|
||||
<option name="scriptParameters" value="" />
|
||||
<option name="taskDescriptions">
|
||||
<list />
|
||||
</option>
|
||||
<option name="taskNames">
|
||||
<list>
|
||||
<option value="runIde" />
|
||||
</list>
|
||||
</option>
|
||||
<option name="vmOptions" value="" />
|
||||
</ExternalSystemSettings>
|
||||
<method />
|
||||
</configuration>
|
||||
</component>
|
41
experimental/intellij-plugin/build.gradle
Normal file
41
experimental/intellij-plugin/build.gradle
Normal file
@ -0,0 +1,41 @@
|
||||
buildscript {
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
}
|
||||
}
|
||||
|
||||
plugins {
|
||||
id "org.jetbrains.intellij" version "0.2.11"
|
||||
}
|
||||
|
||||
apply plugin: 'kotlin'
|
||||
|
||||
intellij {
|
||||
version 'IU-2017.1'
|
||||
//IntelliJ IDEA 2016.3 dependency; for a full list of IntelliJ IDEA releases please see https://www.jetbrains.com/intellij-repository/releases
|
||||
plugins = ['Kotlin', 'devkit', 'gradle'] //Bundled plugin dependencies
|
||||
pluginName "$project.name"
|
||||
|
||||
updateSinceUntilBuild = false
|
||||
sameSinceUntilBuild = false
|
||||
|
||||
buildDir = "$projectDir/build"
|
||||
}
|
||||
|
||||
group 'net.corda'
|
||||
version '0.1.0' // Plugin version
|
||||
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
main{
|
||||
java.srcDirs += 'src/main/kotlin'
|
||||
resources.srcDirs += 'src/main/resources'
|
||||
}
|
||||
}
|
1
experimental/intellij-plugin/gradle.properties
Normal file
1
experimental/intellij-plugin/gradle.properties
Normal file
@ -0,0 +1 @@
|
||||
kotlin_version=1.1.2-2
|
25
experimental/intellij-plugin/readme.md
Normal file
25
experimental/intellij-plugin/readme.md
Normal file
@ -0,0 +1,25 @@
|
||||
# Corda Intellij Plugin
|
||||
|
||||
Corda Intellij Plugin is a plugin for Intellij Idea IDE which aid Corda application development.
|
||||
|
||||
## Features
|
||||
* Setup CorDapp project in a few clicks.
|
||||
* Support Java and Kotlin project.
|
||||
* User can choose to include different Corda module templates.
|
||||
|
||||
## Getting started
|
||||
This project uses gradle to manage dependencies, Intellij's Plugin runner DOES NOT work in this project.
|
||||
|
||||
###Running the project
|
||||
You can run or debug the project using provided Intellij Run Configuration `CordaPlugin` or by using the gradle command
|
||||
`./gradlew runIde` IDE's log file is located in `build/idea-sandbox/system/log/idea.log`
|
||||
|
||||
## TODOs
|
||||
* Create a higher quality Corda icon.
|
||||
* Create a more compact kotlin CorDapp template.
|
||||
* Add Java Templates.
|
||||
* Figure out how to import gradle setting in the plugin, to avoid having to manual import after project creation.
|
||||
* Support other build tools? (Maven, SBT etc...)
|
||||
* Custom run configuration for running and debugging CorDapp in Intellij.
|
||||
* Add Python option?
|
||||
* Flow visualiser?
|
1
experimental/intellij-plugin/settings.gradle
Normal file
1
experimental/intellij-plugin/settings.gradle
Normal file
@ -0,0 +1 @@
|
||||
rootProject.name = "CordaPlugin"
|
@ -0,0 +1,104 @@
|
||||
package net.corda.ideaPlugin.module
|
||||
|
||||
import com.intellij.ide.fileTemplates.FileTemplateManager
|
||||
import com.intellij.ide.projectWizard.ProjectSettingsStep
|
||||
import com.intellij.ide.util.projectWizard.*
|
||||
import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.module.ModuleType
|
||||
import com.intellij.openapi.options.ConfigurationException
|
||||
import com.intellij.openapi.util.Version
|
||||
import com.intellij.openapi.util.io.FileUtilRt
|
||||
import com.intellij.openapi.vfs.LocalFileSystem
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import org.jetbrains.plugins.gradle.service.project.wizard.GradleModuleBuilder.appendToFile
|
||||
import org.jetbrains.plugins.gradle.service.project.wizard.GradleModuleBuilder.setupGradleSettingsFile
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
|
||||
class CordaModuleBuilder : JavaModuleBuilder(), ModuleBuilderListener {
|
||||
private val config = CordaModuleConfiguration()
|
||||
|
||||
init {
|
||||
addListener(this)
|
||||
}
|
||||
|
||||
override fun getBuilderId() = "corda"
|
||||
|
||||
override fun moduleCreated(module: Module) {
|
||||
val contentEntryPath = contentEntryPath
|
||||
if (contentEntryPath.isNullOrEmpty()) return
|
||||
val contentRootDir = File(contentEntryPath)
|
||||
FileUtilRt.createDirectory(contentRootDir)
|
||||
val fileSystem = LocalFileSystem.getInstance()
|
||||
val modelContentRootDir = fileSystem.refreshAndFindFileByIoFile(contentRootDir) ?: return
|
||||
|
||||
val packagePath = "src/main/kotlin/${config.packageName.replace(".", "/")}"
|
||||
setupGradleSettingsFile(modelContentRootDir.path, modelContentRootDir, module.project.name, module.name, true)
|
||||
setupFile(modelContentRootDir, "", "build.gradle", "build.gradle")
|
||||
|
||||
config.selectedTemplate.flatMap { CordaTemplateProvider.getTemplateFiles(it, config.language) }.forEach {
|
||||
setupFile(modelContentRootDir, "$packagePath/${it.targetPath}", "${if (it.appendProjectName) config.appName else ""}${it.fileName}", it.fileName)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getCustomOptionsStep(context: WizardContext, parentDisposable: Disposable?) = CordaModuleWizardStep(config)
|
||||
|
||||
override fun modifySettingsStep(settingsStep: SettingsStep): ModuleWizardStep? {
|
||||
if (settingsStep is ProjectSettingsStep) {
|
||||
val projectSettingsStep = settingsStep
|
||||
val moduleNameField = settingsStep.moduleNameField
|
||||
moduleNameField.text = config.appName
|
||||
projectSettingsStep.setModuleName(config.packageName)
|
||||
projectSettingsStep.bindModuleSettings()
|
||||
}
|
||||
return super.modifySettingsStep(settingsStep)
|
||||
}
|
||||
|
||||
override fun getPresentableName() = "CorDapp"
|
||||
|
||||
override fun getGroupName() = "Corda"
|
||||
|
||||
override fun getModuleType(): ModuleType<*> = CordaModuleType.instance
|
||||
|
||||
private fun setupFile(modelContentRootDir: VirtualFile, path: String, fileName: String, templateName: String): VirtualFile? {
|
||||
val file = getOrCreateExternalProjectConfigFile("${modelContentRootDir.path}/$path", fileName) ?: return null
|
||||
saveFile(file, templateName, config.toMap())
|
||||
return file
|
||||
}
|
||||
|
||||
private fun getOrCreateExternalProjectConfigFile(parent: String, fileName: String): VirtualFile? {
|
||||
val file = File(parent, fileName)
|
||||
FileUtilRt.createIfNotExists(file)
|
||||
return LocalFileSystem.getInstance().refreshAndFindFileByIoFile(file)
|
||||
}
|
||||
|
||||
private fun saveFile(file: VirtualFile, templateName: String, templateAttributes: Map<String, String?>?) {
|
||||
val manager = FileTemplateManager.getDefaultInstance()
|
||||
val template = manager.getInternalTemplate(templateName)
|
||||
try {
|
||||
appendToFile(file, if (templateAttributes != null) template.getText(templateAttributes) else template.text)
|
||||
} catch (e: IOException) {
|
||||
throw ConfigurationException(e.message, e.stackTrace.toString())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data class CordaModuleConfiguration(var cordaSdkVersion: Version? = null,
|
||||
var group: String = "",
|
||||
var appName: String = "",
|
||||
var packageName: String = "",
|
||||
var version: String = "",
|
||||
var language: Language = Language.KOTLIN,
|
||||
var selectedTemplate: List<CordaTemplate> = emptyList()) {
|
||||
|
||||
fun toMap(): Map<String, String> {
|
||||
return mapOf("CORDA_SDK_VERSION" to cordaSdkVersion.toString(),
|
||||
"PROJECT_NAME" to appName,
|
||||
"PROJECT_NAME_DECAPITALIZE" to appName.decapitalize(),
|
||||
"PACKAGE_NAME" to packageName,
|
||||
"VERSION" to version,
|
||||
"GROUP" to group,
|
||||
"LANGUAGE" to language.displayName)
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package net.corda.ideaPlugin.module
|
||||
|
||||
import com.intellij.openapi.module.ModuleType
|
||||
import com.intellij.openapi.util.IconLoader
|
||||
|
||||
class CordaModuleType : ModuleType<CordaModuleBuilder>(ID) {
|
||||
companion object {
|
||||
val ID = "CORDA_MODULE"
|
||||
val CORDA_ICON = IconLoader.getIcon("/images/corda-icon.png")
|
||||
val instance = CordaModuleType()
|
||||
}
|
||||
|
||||
override fun createModuleBuilder() = CordaModuleBuilder()
|
||||
override fun getNodeIcon(p0: Boolean) = CORDA_ICON
|
||||
override fun getBigIcon() = CORDA_ICON
|
||||
override fun getName() = "CorDapp"
|
||||
override fun getDescription() = "Corda DLT Platform Application"
|
||||
}
|
||||
|
@ -0,0 +1,88 @@
|
||||
package net.corda.ideaPlugin.module
|
||||
|
||||
import com.intellij.ide.util.projectWizard.ModuleWizardStep
|
||||
import com.intellij.openapi.options.ConfigurationException
|
||||
import com.intellij.openapi.util.Version
|
||||
import com.intellij.ui.CheckBoxList
|
||||
import com.intellij.ui.components.JBScrollPane
|
||||
import com.intellij.ui.components.JBTextField
|
||||
import com.intellij.ui.layout.CCFlags
|
||||
import com.intellij.ui.layout.panel
|
||||
import java.awt.BorderLayout
|
||||
import javax.swing.*
|
||||
|
||||
class CordaModuleWizardStep(private val config: CordaModuleConfiguration) : ModuleWizardStep() {
|
||||
private val sdkPanel = CordaModuleWizardPanel()
|
||||
|
||||
override fun getComponent() = sdkPanel
|
||||
|
||||
override fun updateDataModel() {
|
||||
config.cordaSdkVersion = sdkPanel.cordaSdkVersion
|
||||
config.language = sdkPanel.language!!
|
||||
config.appName = sdkPanel.appName
|
||||
config.packageName = "${sdkPanel.domain}.${sdkPanel.appName.decapitalize()}"
|
||||
config.group = sdkPanel.domain
|
||||
config.version = sdkPanel.version
|
||||
config.selectedTemplate = sdkPanel.templates
|
||||
}
|
||||
|
||||
@Throws(ConfigurationException::class)
|
||||
override fun validate(): Boolean {
|
||||
sdkPanel.cordaSdkVersion ?: throw ConfigurationException("Specify Corda SDK Version")
|
||||
return super.validate()
|
||||
}
|
||||
}
|
||||
|
||||
class CordaModuleWizardPanel : JPanel(BorderLayout()) {
|
||||
val cordaSdkVersion: Version? get() = cordaSdkVersionComboBox.getSelectedCordaSdkVersion()
|
||||
val language: Language? get() = languageComboBox.selectedItem as? Language
|
||||
val appName: String get() = appNameTextField.text
|
||||
val domain: String get() = domainTextField.text
|
||||
val version: String get() = versionTextField.text
|
||||
val templates: List<CordaTemplate> get() = CordaTemplate.values().filter { templateList.isItemSelected(it) }
|
||||
|
||||
private val cordaSdkVersionComboBox = CordaSdkVersionComboBox(Version(0, 12, 1), Version(0, 11, 1))
|
||||
private val languageComboBox = JComboBox(DefaultComboBoxModel(Language.values()))
|
||||
private val appNameTextField = JBTextField("MyCorDapp")
|
||||
private val domainTextField = JBTextField("com.myCompany")
|
||||
private val versionTextField = JBTextField("1.0.0")
|
||||
private val templateList = CheckBoxList<CordaTemplate>().apply {
|
||||
CordaTemplate.values().forEach {
|
||||
addItem(it, it.displayName, it == CordaTemplate.CORDAPP)
|
||||
}
|
||||
setCheckBoxListListener { i, _ ->
|
||||
val template = getItemAt(i) as? CordaTemplate
|
||||
template?.let { if (!it.optional) setItemSelected(it, true) }
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
val myRoot = panel {
|
||||
border = BorderFactory.createEmptyBorder(4, 5, 0, 5)
|
||||
//row("Project SDK:") { projectSdkComboBox(CCFlags.growX, CCFlags.pushX) }
|
||||
row("Corda SDK Version:") { cordaSdkVersionComboBox(CCFlags.growX, CCFlags.pushX) }
|
||||
row("Language:") { languageComboBox(CCFlags.growX, CCFlags.pushX) }
|
||||
row(JLabel("CorDapp Name:"), separated = true) { appNameTextField(CCFlags.growX, CCFlags.pushX) }
|
||||
row("Company Domain:") { domainTextField(CCFlags.growX, CCFlags.pushX) }
|
||||
//TODO: row("Package Name:") { packageName(CCFlags.growX, CCFlags.pushX) }
|
||||
row("Version:") { versionTextField(CCFlags.growX, CCFlags.pushX) }
|
||||
}
|
||||
|
||||
val template = panel {
|
||||
row(separated = true) { (JLabel("Templates and Examples:"))(CCFlags.growX, CCFlags.pushX) }
|
||||
row { (JBScrollPane(templateList))(CCFlags.grow, CCFlags.push) }
|
||||
}
|
||||
add(myRoot, BorderLayout.NORTH)
|
||||
add(template, BorderLayout.CENTER)
|
||||
languageComboBox.selectedItem = Language.KOTLIN
|
||||
}
|
||||
}
|
||||
|
||||
enum class Language(val displayName: String) {
|
||||
JAVA("Java"),
|
||||
KOTLIN("Kotlin");
|
||||
|
||||
override fun toString(): String {
|
||||
return displayName
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package net.corda.ideaPlugin.module
|
||||
|
||||
import com.intellij.openapi.util.Version
|
||||
import com.intellij.ui.ColoredListCellRenderer
|
||||
import com.intellij.ui.SimpleTextAttributes
|
||||
import javax.swing.DefaultComboBoxModel
|
||||
import javax.swing.JComboBox
|
||||
import javax.swing.JList
|
||||
|
||||
class CordaSdkVersionComboBox(vararg val sdkVersions: Version) : JComboBox<Version>() {
|
||||
init {
|
||||
renderer = object : ColoredListCellRenderer<Any?>() {
|
||||
override fun customizeCellRenderer(list: JList<*>, value: Any?, index: Int, selected: Boolean, hasFocus: Boolean) {
|
||||
if (value is Version) {
|
||||
append(value.toString())
|
||||
} else {
|
||||
append("Select Corda SDK Version", SimpleTextAttributes.ERROR_ATTRIBUTES)
|
||||
}
|
||||
}
|
||||
}
|
||||
updateSdkList(null, true)
|
||||
}
|
||||
|
||||
fun updateSdkList(sdkVersionToSelect: Version?, selectAnySdk: Boolean) {
|
||||
model = DefaultComboBoxModel(arrayOf(null, *sdkVersions))
|
||||
selectedItem = if (selectAnySdk) sdkVersions.firstOrNull() else sdkVersionToSelect
|
||||
}
|
||||
|
||||
fun getSelectedCordaSdkVersion() = selectedItem as? Version
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
package net.corda.ideaPlugin.module
|
||||
|
||||
object CordaTemplateProvider {
|
||||
fun getTemplateFiles(cordaTemplate: CordaTemplate, language: Language): List<TemplateFile> {
|
||||
return when (language) {
|
||||
Language.KOTLIN -> getKotlinTemplateFiles(cordaTemplate)
|
||||
Language.JAVA -> getJavaTemplateFiles(cordaTemplate)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getKotlinTemplateFiles(cordaTemplate: CordaTemplate): List<TemplateFile> {
|
||||
return when (cordaTemplate) {
|
||||
CordaTemplate.CORDAPP -> listOf(
|
||||
TemplateFile("Main.kt", "", appendProjectName = false),
|
||||
TemplateFile("Flow.kt", "/flow"),
|
||||
TemplateFile("Contract.kt", "/contract"),
|
||||
TemplateFile("State.kt", "/state"))
|
||||
CordaTemplate.WEBAPI -> listOf(
|
||||
TemplateFile("Api.kt", "/api"),
|
||||
TemplateFile("Plugin.kt", "/plugin"))
|
||||
CordaTemplate.RPC -> listOf(TemplateFile("ClientRPC.kt", "/client"))
|
||||
}
|
||||
}
|
||||
|
||||
private fun getJavaTemplateFiles(cordaTemplate: CordaTemplate): List<TemplateFile> {
|
||||
// TODO: Provide java template.
|
||||
return when (cordaTemplate) {
|
||||
CordaTemplate.CORDAPP -> listOf()
|
||||
CordaTemplate.WEBAPI -> listOf()
|
||||
CordaTemplate.RPC -> listOf()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum class CordaTemplate(val displayName: String, val optional: Boolean = true) {
|
||||
CORDAPP("CorDapp Template", optional = false),
|
||||
WEBAPI("Web API Template"),
|
||||
RPC("RPC Client Template")
|
||||
}
|
||||
|
||||
data class TemplateFile(val fileName: String, val targetPath: String, val appendProjectName: Boolean = true)
|
@ -0,0 +1,36 @@
|
||||
<idea-plugin>
|
||||
<id>net.corda</id>
|
||||
<name>CorDapp Plugin</name>
|
||||
<version>1.0</version>
|
||||
<vendor email="support@yourcompany.com" url="http://www.yourcompany.com">YourCompany</vendor>
|
||||
|
||||
<description><![CDATA[
|
||||
Enter short description for your plugin here.<br>
|
||||
<em>most HTML tags may be used</em>
|
||||
]]></description>
|
||||
|
||||
<change-notes><![CDATA[
|
||||
Add change notes here.<br>
|
||||
<em>most HTML tags may be used</em>
|
||||
]]>
|
||||
</change-notes>
|
||||
|
||||
<!-- please see http://www.jetbrains.org/intellij/sdk/docs/basics/getting_started/build_number_ranges.html for description -->
|
||||
<idea-version since-build="145.0"/>
|
||||
|
||||
<!-- please see http://www.jetbrains.org/intellij/sdk/docs/basics/getting_started/plugin_compatibility.html
|
||||
on how to target different products -->
|
||||
<depends>com.intellij.modules.lang</depends>
|
||||
<depends>org.jetbrains.kotlin</depends>
|
||||
<depends>DevKit</depends>
|
||||
<depends>org.jetbrains.plugins.gradle</depends>
|
||||
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<moduleType id="CORDA_MODULE" implementationClass="net.corda.ideaPlugin.module.CordaModuleType"/>
|
||||
</extensions>
|
||||
|
||||
<actions>
|
||||
<!-- Add your actions here -->
|
||||
</actions>
|
||||
|
||||
</idea-plugin>
|
@ -0,0 +1,32 @@
|
||||
package ${PACKAGE_NAME}.api
|
||||
|
||||
import net.corda.core.messaging.CordaRPCOps
|
||||
import javax.ws.rs.GET
|
||||
import javax.ws.rs.PUT
|
||||
import javax.ws.rs.Path
|
||||
import javax.ws.rs.Produces
|
||||
import javax.ws.rs.core.MediaType
|
||||
import javax.ws.rs.core.Response
|
||||
|
||||
// This API is accessible from /api/${PROJECT_NAME_DECAPITALIZE}. The endpoint paths specified below are relative to it.
|
||||
@Path("${PROJECT_NAME_DECAPITALIZE}")
|
||||
class ${PROJECT_NAME}Api(val services: CordaRPCOps) {
|
||||
/**
|
||||
* Accessible at /api/template/${PROJECT_NAME_DECAPITALIZE}GetEndpoint.
|
||||
*/
|
||||
@GET
|
||||
@Path("${PROJECT_NAME_DECAPITALIZE}GetEndpoint")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
fun templateGetEndpoint(): Response {
|
||||
return Response.ok(mapOf("message" to "${PROJECT_NAME} GET endpoint.")).build()
|
||||
}
|
||||
|
||||
/**
|
||||
* Accessible at /api/template/${PROJECT_NAME_DECAPITALIZE}PutEndpoint.
|
||||
*/
|
||||
@PUT
|
||||
@Path("${PROJECT_NAME_DECAPITALIZE}PutEndpoint")
|
||||
fun templatePutEndpoint(payload: Any): Response {
|
||||
return Response.ok("${PROJECT_NAME} PUT endpoint.").build()
|
||||
}
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
package ${PACKAGE_NAME}.client
|
||||
|
||||
import com.google.common.net.HostAndPort
|
||||
import ${PACKAGE_NAME}.state.${PROJECT_NAME}State
|
||||
import net.corda.client.rpc.CordaRPCClient
|
||||
import net.corda.core.transactions.SignedTransaction
|
||||
import net.corda.core.utilities.loggerFor
|
||||
import org.slf4j.Logger
|
||||
import rx.Observable
|
||||
|
||||
/**
|
||||
* Demonstration of how to use the CordaRPCClient to connect to a Corda Node and
|
||||
* stream some State data from the node.
|
||||
*/
|
||||
fun main(args: Array<String>) {
|
||||
${PROJECT_NAME}ClientRPC().main(args)
|
||||
}
|
||||
|
||||
private class ${PROJECT_NAME}ClientRPC {
|
||||
companion object {
|
||||
val logger: Logger = loggerFor<${PROJECT_NAME}ClientRPC>()
|
||||
}
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
require(args.size == 1) { "Usage: ${PROJECT_NAME}ClientRPC <node address>" }
|
||||
val nodeAddress = HostAndPort.fromString(args[0])
|
||||
val client = CordaRPCClient(nodeAddress)
|
||||
|
||||
// Can be amended in the com.template.MainKt file.
|
||||
val proxy = client.start("user1", "test").proxy
|
||||
|
||||
// Grab all signed transactions and all future signed transactions.
|
||||
val (transactions: List<SignedTransaction>, futureTransactions: Observable<SignedTransaction>) =
|
||||
proxy.verifiedTransactions()
|
||||
|
||||
// Log the existing TemplateStates and listen for new ones.
|
||||
futureTransactions.startWith(transactions).toBlocking().subscribe { transaction ->
|
||||
transaction.tx.outputs.forEach { output ->
|
||||
val state = output.data as ${PROJECT_NAME}State
|
||||
logger.info(state.toString())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package ${PACKAGE_NAME}.contract
|
||||
|
||||
import net.corda.core.contracts.Contract
|
||||
import net.corda.core.contracts.TransactionForContract
|
||||
import net.corda.core.crypto.SecureHash
|
||||
|
||||
/**
|
||||
* Define your contract here.
|
||||
*/
|
||||
open class ${PROJECT_NAME}Contract : Contract {
|
||||
/**
|
||||
* The verify() function of the contract of each of the transaction's input and output states must not throw an
|
||||
* exception for a transaction to be considered valid.
|
||||
*/
|
||||
override fun verify(tx: TransactionForContract) {}
|
||||
|
||||
/** A reference to the underlying legal contract template and associated parameters. */
|
||||
override val legalContractReference: SecureHash = SecureHash.sha256("Prose contract.")
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
package ${PACKAGE_NAME}.flow
|
||||
|
||||
import co.paralleluniverse.fibers.Suspendable
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.flows.FlowLogic
|
||||
import net.corda.core.flows.InitiatedBy
|
||||
import net.corda.core.flows.InitiatingFlow
|
||||
|
||||
/**
|
||||
* Define your flow here.
|
||||
*/
|
||||
object ${PROJECT_NAME}Flow {
|
||||
/**
|
||||
* You can add a constructor to each FlowLogic subclass to pass objects into the flow.
|
||||
*/
|
||||
@InitiatingFlow
|
||||
class Initiator: FlowLogic<Unit>() {
|
||||
/**
|
||||
* Define the initiator's flow logic here.
|
||||
*/
|
||||
@Suspendable
|
||||
override fun call() {}
|
||||
}
|
||||
|
||||
@InitiatedBy(Initiator::class)
|
||||
class Acceptor(val counterparty: Party) : FlowLogic<Unit>() {
|
||||
/**
|
||||
* Define the acceptor's flow logic here.
|
||||
*/
|
||||
@Suspendable
|
||||
override fun call() {}
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
package ${PACKAGE_NAME}
|
||||
|
||||
import com.google.common.util.concurrent.Futures
|
||||
import net.corda.core.crypto.X509Utilities.getX509Name
|
||||
import net.corda.core.getOrThrow
|
||||
import net.corda.core.node.services.ServiceInfo
|
||||
import net.corda.node.driver.driver
|
||||
import net.corda.nodeapi.User
|
||||
import net.corda.node.services.transactions.ValidatingNotaryService
|
||||
|
||||
/**
|
||||
* This file is exclusively for being able to run your nodes through an IDE (as opposed to running deployNodes)
|
||||
* Do not use in a production environment.
|
||||
*
|
||||
* To debug your CorDapp:
|
||||
*
|
||||
* 1. Run the "Run ${PROJECT_NAME} CorDapp" run configuration.
|
||||
* 2. Wait for all the nodes to start.
|
||||
* 3. Note the debug ports for each node, which should be output to the console. The "Debug CorDapp" configuration runs
|
||||
* with port 5007, which should be "NodeA". In any case, double-check the console output to be sure.
|
||||
* 4. Set your breakpoints in your CorDapp code.
|
||||
* 5. Run the "Debug CorDapp" remote debug run configuration.
|
||||
*/
|
||||
fun main(args: Array<String>) {
|
||||
// No permissions required as we are not invoking flows.
|
||||
val user = User("user1", "test", permissions = setOf())
|
||||
driver(isDebug = true) {
|
||||
startNode(getX509Name("Controller", "London", "root@city.uk.example"), setOf(ServiceInfo(ValidatingNotaryService.type)))
|
||||
val (nodeA, nodeB, nodeC) = Futures.allAsList(
|
||||
startNode(getX509Name("NodeA", "Paris", "root@city.fr.example"), rpcUsers = listOf(user)),
|
||||
startNode(getX509Name("NodeB", "Rome", "root@city.it.example"), rpcUsers = listOf(user)),
|
||||
startNode(getX509Name("NodeC", "New York", "root@city.us.example"), rpcUsers = listOf(user))).getOrThrow()
|
||||
|
||||
startWebserver(nodeA)
|
||||
startWebserver(nodeB)
|
||||
startWebserver(nodeC)
|
||||
|
||||
waitForAllNodesToFinish()
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package ${PACKAGE_NAME}.plugin
|
||||
|
||||
import ${PACKAGE_NAME}.api.${PROJECT_NAME}Api
|
||||
import net.corda.core.messaging.CordaRPCOps
|
||||
import net.corda.core.node.CordaPluginRegistry
|
||||
import net.corda.core.serialization.SerializationCustomization
|
||||
import java.util.function.Function
|
||||
|
||||
class ${PROJECT_NAME}Plugin : CordaPluginRegistry() {
|
||||
/**
|
||||
* A list of classes that expose web APIs.
|
||||
*/
|
||||
override val webApis: List<Function<CordaRPCOps, out Any>> = listOf(Function(::${PROJECT_NAME}Api))
|
||||
|
||||
/**
|
||||
* A list of directories in the resources directory that will be served by Jetty under /web.
|
||||
* The template's web frontend is accessible at /web/template.
|
||||
*/
|
||||
override val staticServeDirs: Map<String, String> = mapOf(
|
||||
// This will serve the ${PROJECT_NAME_DECAPITALIZE}Web directory in resources to /web/${PROJECT_NAME_DECAPITALIZE}
|
||||
"${PROJECT_NAME_DECAPITALIZE}" to javaClass.classLoader.getResource("${PROJECT_NAME_DECAPITALIZE}Web").toExternalForm()
|
||||
)
|
||||
|
||||
/**
|
||||
* Whitelisting the required types for serialisation by the Corda node.
|
||||
*/
|
||||
override fun customizeSerialization(custom: SerializationCustomization): Boolean {
|
||||
return true
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
package ${PACKAGE_NAME}.state
|
||||
|
||||
import ${PACKAGE_NAME}.contract.${PROJECT_NAME}Contract
|
||||
import net.corda.core.contracts.ContractState
|
||||
import net.corda.core.identity.AbstractParty
|
||||
|
||||
/**
|
||||
* Define your state object here.
|
||||
*/
|
||||
class ${PROJECT_NAME}State(override val contract: ${PROJECT_NAME}Contract): ContractState {
|
||||
/** The public keys of the involved parties. */
|
||||
override val participants: List<AbstractParty>
|
||||
get() = listOf()
|
||||
}
|
@ -0,0 +1,162 @@
|
||||
buildscript {
|
||||
ext.corda_release_version = '${CORDA_SDK_VERSION}'
|
||||
ext.corda_gradle_plugins_version = '0.11.2'
|
||||
ext.kotlin_version = '1.1.2'
|
||||
ext.junit_version = '4.12'
|
||||
ext.quasar_version = '0.7.6'
|
||||
|
||||
repositories {
|
||||
mavenLocal()
|
||||
mavenCentral()
|
||||
jcenter()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
classpath "net.corda.plugins:publish-utils:$corda_gradle_plugins_version"
|
||||
classpath "net.corda.plugins:cordformation:$corda_gradle_plugins_version"
|
||||
classpath "net.corda.plugins:quasar-utils:$corda_gradle_plugins_version"
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'java'
|
||||
apply plugin: 'kotlin'
|
||||
apply plugin: 'idea'
|
||||
apply plugin: 'net.corda.plugins.publish-utils'
|
||||
apply plugin: 'net.corda.plugins.cordformation'
|
||||
apply plugin: 'net.corda.plugins.quasar-utils'
|
||||
apply plugin: 'maven-publish'
|
||||
|
||||
group '${GROUP}'
|
||||
version '${VERSION}'
|
||||
|
||||
repositories {
|
||||
mavenLocal()
|
||||
mavenCentral()
|
||||
jcenter()
|
||||
maven { url 'https://dl.bintray.com/kotlin/exposed' }
|
||||
maven { url 'https://jitpack.io' }
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
main {
|
||||
resources {
|
||||
srcDir "config/dev"
|
||||
}
|
||||
}
|
||||
test {
|
||||
resources {
|
||||
srcDir "config/test"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlin_version"
|
||||
testCompile "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
|
||||
testCompile "junit:junit:$junit_version"
|
||||
|
||||
// Corda integration dependencies
|
||||
compile "net.corda:core:$corda_release_version"
|
||||
compile "net.corda:finance:$corda_release_version"
|
||||
compile "net.corda:jackson:$corda_release_version"
|
||||
compile "net.corda:node:$corda_release_version"
|
||||
compile "net.corda:rpc:$corda_release_version"
|
||||
compile "net.corda:webserver:$corda_release_version"
|
||||
runtime "net.corda:corda:$corda_release_version"
|
||||
runtime "net.corda:webserver:$corda_release_version"
|
||||
|
||||
testCompile "net.corda:test-utils:$corda_release_version"
|
||||
|
||||
// GraphStream: For visualisation (required by TemplateClientRPC app)
|
||||
compile "org.graphstream:gs-core:1.3"
|
||||
compile("org.graphstream:gs-ui:1.3") {
|
||||
exclude group: "bouncycastle"
|
||||
}
|
||||
|
||||
// CorDapp dependencies
|
||||
// Specify your cordapp's dependencies below, including dependent cordapps
|
||||
}
|
||||
|
||||
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
|
||||
kotlinOptions {
|
||||
languageVersion = "1.1"
|
||||
apiVersion = "1.1"
|
||||
jvmTarget = "1.8"
|
||||
javaParameters = true // Useful for reflection.
|
||||
}
|
||||
}
|
||||
|
||||
task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) {
|
||||
directory "./build/nodes"
|
||||
networkMap "CN=Controller,O=R3,OU=corda,L=London,C=UK"
|
||||
node {
|
||||
name "CN=Controller,O=R3,OU=corda,L=London,C=UK"
|
||||
advertisedServices = ["corda.notary.validating"]
|
||||
p2pPort 10002
|
||||
rpcPort 10003
|
||||
cordapps = []
|
||||
}
|
||||
node {
|
||||
name "CN=NodeA,O=NodeA,L=London,C=UK"
|
||||
advertisedServices = []
|
||||
p2pPort 10005
|
||||
rpcPort 10006
|
||||
webPort 10007
|
||||
cordapps = []
|
||||
rpcUsers = [[user: "user1", "password": "test", "permissions": []]]
|
||||
}
|
||||
node {
|
||||
name "CN=NodeB,O=NodeB,L=New York,C=US"
|
||||
advertisedServices = []
|
||||
p2pPort 10008
|
||||
rpcPort 10009
|
||||
webPort 10010
|
||||
cordapps = []
|
||||
rpcUsers = [[user: "user1", "password": "test", "permissions": []]]
|
||||
}
|
||||
node {
|
||||
name "CN=NodeC,O=NodeC,L=Paris,C=FR"
|
||||
advertisedServices = []
|
||||
p2pPort 10011
|
||||
rpcPort 10012
|
||||
webPort 10013
|
||||
cordapps = []
|
||||
rpcUsers = [[user: "user1", "password": "test", "permissions": []]]
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Make into gradle plugin without any references to Jython
|
||||
task installJythonDeps(dependsOn: ['build']) {
|
||||
project.copy {
|
||||
from project.configurations.runtime
|
||||
into "build/jythonDeps"
|
||||
}
|
||||
}
|
||||
|
||||
installJythonDeps.shouldRunAfter build
|
||||
|
||||
idea {
|
||||
module {
|
||||
downloadJavadoc = true // defaults to false
|
||||
downloadSources = true
|
||||
}
|
||||
}
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
jarAndSources(MavenPublication) {
|
||||
from components.java
|
||||
artifactId 'cordapp-name-goes-here'
|
||||
|
||||
artifact sourceJar
|
||||
artifact javadocJar
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
task runTemplateClientRPC(type: JavaExec) {
|
||||
classpath = sourceSets.main.runtimeClasspath
|
||||
main = 'com.template.client.TemplateClientRPCKt'
|
||||
args 'localhost:10006'
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
@ -18,6 +18,7 @@ include 'webserver:webcapsule'
|
||||
include 'experimental'
|
||||
include 'experimental:sandbox'
|
||||
include 'experimental:quasar-hook'
|
||||
include 'experimental:intellij-plugin'
|
||||
include 'verifier'
|
||||
include 'test-utils'
|
||||
include 'tools:explorer'
|
||||
|
Loading…
Reference in New Issue
Block a user