mirror of
https://github.com/corda/corda.git
synced 2025-03-10 22:44:20 +00:00
Merge branch 'master' into clint-irsdemowindowsfix
This commit is contained in:
commit
f74fc67737
36
build.gradle
36
build.gradle
@ -6,17 +6,29 @@ buildscript {
|
||||
// Our version: bump this on release.
|
||||
ext.corda_version = "0.7-SNAPSHOT"
|
||||
ext.gradle_plugins_version = props.getProperty("gradlePluginsVersion")
|
||||
|
||||
// Dependency versions. Can run 'gradle dependencyUpdates' to find new versions of things.
|
||||
//
|
||||
// TODO: Sort this alphabetically.
|
||||
ext.kotlin_version = '1.0.5-2'
|
||||
ext.quasar_version = '0.7.6'
|
||||
ext.quasar_version = '0.7.6' // TODO: Upgrade to 0.7.7+ when Quasar bug 238 is resolved.
|
||||
ext.asm_version = '0.5.3'
|
||||
ext.artemis_version = '1.4.0'
|
||||
ext.jackson_version = '2.8.0.rc2'
|
||||
ext.artemis_version = '1.5.1'
|
||||
ext.jackson_version = '2.8.5'
|
||||
ext.jetty_version = '9.3.9.v20160517'
|
||||
ext.jersey_version = '2.23.1'
|
||||
ext.jolokia_version = '2.0.0-M1'
|
||||
ext.assertj_version = '3.5.1'
|
||||
ext.log4j_version = '2.6.2'
|
||||
ext.bouncycastle_version = '1.54'
|
||||
ext.jersey_version = '2.25'
|
||||
ext.jolokia_version = '2.0.0-M3'
|
||||
ext.assertj_version = '3.6.1'
|
||||
ext.log4j_version = '2.7'
|
||||
ext.bouncycastle_version = '1.56'
|
||||
ext.guava_version = '19.0'
|
||||
ext.quickcheck_version = '0.7'
|
||||
ext.okhttp_version = '3.5.0'
|
||||
ext.typesafe_config_version = '1.3.1'
|
||||
ext.junit_version = '4.12'
|
||||
ext.jopt_simple_version = '5.0.2'
|
||||
ext.jansi_version = '1.14'
|
||||
ext.hibernate_version = '5.2.6.Final'
|
||||
|
||||
repositories {
|
||||
mavenLocal()
|
||||
@ -33,9 +45,7 @@ buildscript {
|
||||
classpath "net.corda.plugins:publish-utils:$gradle_plugins_version"
|
||||
classpath "net.corda.plugins:quasar-utils:$gradle_plugins_version"
|
||||
classpath "net.corda.plugins:cordformation:$gradle_plugins_version"
|
||||
|
||||
// Can run 'gradle dependencyUpdates' to find new versions of things.
|
||||
classpath 'com.github.ben-manes:gradle-versions-plugin:0.12.0'
|
||||
classpath 'com.github.ben-manes:gradle-versions-plugin:0.13.0'
|
||||
}
|
||||
}
|
||||
|
||||
@ -95,7 +105,7 @@ repositories {
|
||||
// Required for building out the fat JAR.
|
||||
dependencies {
|
||||
compile project(':node')
|
||||
compile "com.google.guava:guava:19.0"
|
||||
compile "com.google.guava:guava:$guava_version"
|
||||
runtime project(path: ":node:capsule", configuration: 'runtimeArtifacts')
|
||||
}
|
||||
|
||||
@ -177,4 +187,4 @@ bintrayConfig {
|
||||
name = 'R3'
|
||||
email = 'dev@corda.net'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,5 +5,6 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile "com.google.guava:guava:19.0"
|
||||
// Cannot use ext.guava_version here :(
|
||||
compile "com.google.guava:guava:20.0"
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ dependencies {
|
||||
compile "org.apache.logging.log4j:log4j-slf4j-impl:${log4j_version}"
|
||||
compile "org.apache.logging.log4j:log4j-core:${log4j_version}"
|
||||
|
||||
compile "com.google.guava:guava:19.0"
|
||||
compile "com.google.guava:guava:$guava_version"
|
||||
|
||||
// ReactFX: Functional reactive UI programming.
|
||||
compile 'org.reactfx:reactfx:2.0-M5'
|
||||
@ -61,16 +61,16 @@ dependencies {
|
||||
compile "org.apache.activemq:artemis-core-client:${artemis_version}"
|
||||
|
||||
// Unit testing helpers.
|
||||
testCompile 'junit:junit:4.12'
|
||||
testCompile "junit:junit:$junit_version"
|
||||
testCompile "org.assertj:assertj-core:${assertj_version}"
|
||||
|
||||
testCompile project(':test-utils')
|
||||
|
||||
// Integration test helpers
|
||||
integrationTestCompile 'junit:junit:4.12'
|
||||
integrationTestCompile "junit:junit:$junit_version"
|
||||
}
|
||||
|
||||
task integrationTest(type: Test) {
|
||||
testClassesDir = sourceSets.integrationTest.output.classesDir
|
||||
classpath = sourceSets.integrationTest.runtimeClasspath
|
||||
}
|
||||
}
|
||||
|
@ -31,11 +31,11 @@ sourceSets {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
testCompile 'junit:junit:4.12'
|
||||
testCompile "junit:junit:$junit_version"
|
||||
testCompile "commons-fileupload:commons-fileupload:1.3.2"
|
||||
|
||||
// Guava: Google test library (collections test suite)
|
||||
testCompile "com.google.guava:guava-testlib:19.0"
|
||||
testCompile "com.google.guava:guava-testlib:$guava_version"
|
||||
|
||||
// Bring in the MockNode infrastructure for writing protocol unit tests.
|
||||
testCompile project(":node")
|
||||
@ -43,7 +43,7 @@ dependencies {
|
||||
|
||||
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||
compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
|
||||
compile "org.jetbrains.kotlinx:kotlinx-support-jdk8:0.2"
|
||||
compile "org.jetbrains.kotlinx:kotlinx-support-jdk8:0.3"
|
||||
compile "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
|
||||
|
||||
// Thread safety annotations
|
||||
@ -56,18 +56,19 @@ dependencies {
|
||||
// AssertJ: for fluent assertions for testing
|
||||
testCompile "org.assertj:assertj-core:${assertj_version}"
|
||||
|
||||
compile 'com.pholser:junit-quickcheck-core:0.6'
|
||||
compile 'com.pholser:junit-quickcheck-generators:0.6'
|
||||
compile "com.pholser:junit-quickcheck-core:$quickcheck_version"
|
||||
compile "com.pholser:junit-quickcheck-generators:$quickcheck_version"
|
||||
|
||||
// Guava: Google utilities library.
|
||||
compile "com.google.guava:guava:19.0"
|
||||
compile "com.google.guava:guava:$guava_version"
|
||||
|
||||
// RxJava: observable streams of events.
|
||||
// TODO: We can't upgrade past 1.1.6 due to a behaviour change in RxJava breaking our code. See PR #99 for discussion. Resolve.
|
||||
compile "io.reactivex:rxjava:1.1.6"
|
||||
|
||||
// Kryo: object graph serialization.
|
||||
compile "com.esotericsoftware:kryo:4.0.0"
|
||||
compile "de.javakaffee:kryo-serializers:0.38"
|
||||
compile "de.javakaffee:kryo-serializers:0.41"
|
||||
|
||||
// Apache JEXL: An embeddable expression evaluation library.
|
||||
// This may be temporary until we experiment with other ways to do on-the-fly contract specialisation via an API.
|
||||
@ -88,4 +89,4 @@ dependencies {
|
||||
|
||||
// RS API: Response type and codes for ApiUtils.
|
||||
compile "javax.ws.rs:javax.ws.rs-api:2.0"
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ package net.corda.core.utilities
|
||||
*/
|
||||
object Emoji {
|
||||
// Unfortunately only Apple has a terminal that can do colour emoji AND an emoji font installed by default.
|
||||
val hasEmojiTerminal by lazy { System.getenv("TERM_PROGRAM") == "Apple_Terminal" }
|
||||
val hasEmojiTerminal by lazy { listOf("Apple_Terminal", "iTerm.app").contains(System.getenv("TERM_PROGRAM")) }
|
||||
|
||||
const val CODE_SANTA_CLAUS = "\ud83c\udf85"
|
||||
const val CODE_DIAMOND = "\ud83d\udd37"
|
||||
|
@ -98,4 +98,4 @@ task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['build']) {
|
||||
'permissions' : ["StartFlow.net.corda.flows.CashFlow"]]
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -28,6 +28,6 @@ dependencies {
|
||||
compile project(':core')
|
||||
compile project(':finance')
|
||||
|
||||
testCompile 'junit:junit:4.12'
|
||||
testCompile "junit:junit:$junit_version"
|
||||
testCompile project(':test-utils')
|
||||
}
|
||||
|
@ -22,10 +22,10 @@ dependencies {
|
||||
compile "org.ow2.asm:asm-commons:$asm_version"
|
||||
|
||||
// JOptSimple: command line option parsing
|
||||
compile "net.sf.jopt-simple:jopt-simple:5.0.1"
|
||||
compile "net.sf.jopt-simple:jopt-simple:$jopt_simple_version"
|
||||
|
||||
// Simple Logging Facade: makes the code independent of the chosen logging framework.
|
||||
compile "org.slf4j:slf4j-api:1.7.21"
|
||||
|
||||
testCompile group: 'junit', name: 'junit', version: '4.11'
|
||||
testCompile "junit:junit:$junit_version"
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ dependencies {
|
||||
compile project(':core')
|
||||
|
||||
testCompile project(':test-utils')
|
||||
testCompile 'junit:junit:4.12'
|
||||
testCompile "junit:junit:$junit_version"
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
@ -30,4 +30,4 @@ sourceSets {
|
||||
srcDir "../config/test"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ buildscript {
|
||||
|
||||
dependencies {
|
||||
classpath "net.corda.plugins:publish-utils:$gradle_plugins_version"
|
||||
classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.4'
|
||||
classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7.3'
|
||||
}
|
||||
}
|
||||
|
||||
@ -48,4 +48,4 @@ bintrayConfig {
|
||||
name = 'R3'
|
||||
email = 'dev@corda.net'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ dependencies {
|
||||
compile gradleApi()
|
||||
compile localGroovy()
|
||||
|
||||
compile "com.typesafe:config:1.3.0"
|
||||
// TypeSafe Config: for simple and human friendly config files.
|
||||
compile "com.typesafe:config:$typesafe_config_version"
|
||||
}
|
||||
|
||||
|
@ -11,4 +11,4 @@ repositories {
|
||||
dependencies {
|
||||
compile gradleApi()
|
||||
compile localGroovy()
|
||||
}
|
||||
}
|
||||
|
@ -66,10 +66,10 @@ dependencies {
|
||||
compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
|
||||
compile "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
|
||||
|
||||
compile "com.google.guava:guava:19.0"
|
||||
compile "com.google.guava:guava:$guava_version"
|
||||
|
||||
// JOpt: for command line flags.
|
||||
compile "net.sf.jopt-simple:jopt-simple:5.0.2"
|
||||
compile "net.sf.jopt-simple:jopt-simple:$jopt_simple_version"
|
||||
|
||||
// Artemis: for reliable p2p message queues.
|
||||
compile "org.apache.activemq:artemis-server:${artemis_version}"
|
||||
@ -77,7 +77,7 @@ dependencies {
|
||||
runtime "org.apache.activemq:artemis-amqp-protocol:${artemis_version}"
|
||||
|
||||
// JAnsi: for drawing things to the terminal in nicely coloured ways.
|
||||
compile "org.fusesource.jansi:jansi:1.13"
|
||||
compile "org.fusesource.jansi:jansi:$jansi_version"
|
||||
|
||||
// GraphStream: For visualisation
|
||||
testCompile "org.graphstream:gs-core:1.3"
|
||||
@ -95,7 +95,7 @@ dependencies {
|
||||
compile "org.eclipse.jetty:jetty-servlet:${jetty_version}"
|
||||
compile "org.eclipse.jetty:jetty-webapp:${jetty_version}"
|
||||
compile "javax.servlet:javax.servlet-api:3.1.0"
|
||||
compile "org.jolokia:jolokia-agent-war:2.0.0-M1"
|
||||
compile "org.jolokia:jolokia-agent-war:$jolokia_version"
|
||||
compile "commons-fileupload:commons-fileupload:1.3.2"
|
||||
|
||||
// Jersey for JAX-RS implementation for use in Jetty
|
||||
@ -121,26 +121,27 @@ dependencies {
|
||||
compile "com.google.jimfs:jimfs:1.1"
|
||||
|
||||
// TypeSafe Config: for simple and human friendly config files.
|
||||
compile "com.typesafe:config:1.3.0"
|
||||
compile "com.typesafe:config:$typesafe_config_version"
|
||||
|
||||
// Unit testing helpers.
|
||||
testCompile 'junit:junit:4.12'
|
||||
testCompile "junit:junit:$junit_version"
|
||||
testCompile "org.assertj:assertj-core:${assertj_version}"
|
||||
|
||||
testCompile 'com.pholser:junit-quickcheck-core:0.6'
|
||||
testCompile "com.pholser:junit-quickcheck-core:$quickcheck_version"
|
||||
|
||||
// For H2 database support in persistence
|
||||
compile "com.h2database:h2:1.4.192"
|
||||
compile "com.h2database:h2:1.4.193"
|
||||
|
||||
// Exposed: Kotlin SQL library - under evaluation
|
||||
// TODO: Upgrade to Exposed 0.7 (has API changes)
|
||||
compile "org.jetbrains.exposed:exposed:0.5.0"
|
||||
|
||||
// SQL connection pooling library
|
||||
compile "com.zaxxer:HikariCP:2.4.7"
|
||||
compile "com.zaxxer:HikariCP:2.5.1"
|
||||
|
||||
// Hibernate: an object relational mapper for writing state objects to the database automatically.
|
||||
compile "org.hibernate:hibernate-core:5.2.2.Final"
|
||||
compile "org.hibernate:hibernate-java8:5.2.2.Final"
|
||||
compile "org.hibernate:hibernate-core:$hibernate_version"
|
||||
compile "org.hibernate:hibernate-java8:$hibernate_version"
|
||||
|
||||
// Capsule is a library for building independently executable fat JARs.
|
||||
compile 'co.paralleluniverse:capsule:1.0.3'
|
||||
@ -151,12 +152,12 @@ dependencies {
|
||||
compile 'io.atomix.catalyst:catalyst-netty:1.1.1'
|
||||
|
||||
// Integration test helpers
|
||||
integrationTestCompile 'junit:junit:4.12'
|
||||
integrationTestCompile "junit:junit:$junit_version"
|
||||
|
||||
testCompile "com.nhaarman:mockito-kotlin:0.6.1"
|
||||
testCompile "com.nhaarman:mockito-kotlin:1.1.0"
|
||||
}
|
||||
|
||||
task integrationTest(type: Test) {
|
||||
testClassesDir = sourceSets.integrationTest.output.classesDir
|
||||
classpath = sourceSets.integrationTest.runtimeClasspath
|
||||
}
|
||||
}
|
||||
|
@ -80,4 +80,4 @@ artifacts {
|
||||
publish {
|
||||
name = 'corda'
|
||||
disableDefaultJar = true
|
||||
}
|
||||
}
|
||||
|
@ -25,49 +25,53 @@ import java.time.LocalDateTime
|
||||
* the java.time API, some core types, and Kotlin data classes.
|
||||
*/
|
||||
object JsonSupport {
|
||||
|
||||
fun createDefaultMapper(identities: IdentityService): ObjectMapper {
|
||||
val mapper = ServiceHubObjectMapper(identities)
|
||||
mapper.enable(SerializationFeature.INDENT_OUTPUT)
|
||||
mapper.enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
|
||||
mapper.enable(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS)
|
||||
|
||||
val timeModule = SimpleModule("java.time")
|
||||
timeModule.addSerializer(LocalDate::class.java, ToStringSerializer)
|
||||
timeModule.addDeserializer(LocalDate::class.java, LocalDateDeserializer)
|
||||
timeModule.addKeyDeserializer(LocalDate::class.java, LocalDateKeyDeserializer)
|
||||
timeModule.addSerializer(LocalDateTime::class.java, ToStringSerializer)
|
||||
|
||||
val cordaModule = SimpleModule("core")
|
||||
cordaModule.addSerializer(Party::class.java, PartySerializer)
|
||||
cordaModule.addDeserializer(Party::class.java, PartyDeserializer)
|
||||
cordaModule.addSerializer(BigDecimal::class.java, ToStringSerializer)
|
||||
cordaModule.addDeserializer(BigDecimal::class.java, NumberDeserializers.BigDecimalDeserializer())
|
||||
cordaModule.addSerializer(SecureHash::class.java, SecureHashSerializer)
|
||||
// It's slightly remarkable, but apparently Jackson works out that this is the only possibility
|
||||
// for a SecureHash at the moment and tries to use SHA256 directly even though we only give it SecureHash
|
||||
cordaModule.addDeserializer(SecureHash.SHA256::class.java, SecureHashDeserializer())
|
||||
cordaModule.addDeserializer(BusinessCalendar::class.java, CalendarDeserializer)
|
||||
|
||||
// For ed25519 pubkeys
|
||||
cordaModule.addSerializer(EdDSAPublicKey::class.java, PublicKeySerializer)
|
||||
cordaModule.addDeserializer(EdDSAPublicKey::class.java, PublicKeyDeserializer)
|
||||
|
||||
// For composite keys
|
||||
cordaModule.addSerializer(CompositeKey::class.java, CompositeKeySerializer)
|
||||
cordaModule.addDeserializer(CompositeKey::class.java, CompositeKeyDeserializer)
|
||||
|
||||
// For NodeInfo
|
||||
// TODO this tunnels the Kryo representation as a Base58 encoded string. Replace when RPC supports this.
|
||||
cordaModule.addSerializer(NodeInfo::class.java, NodeInfoSerializer)
|
||||
cordaModule.addDeserializer(NodeInfo::class.java, NodeInfoDeserializer)
|
||||
|
||||
mapper.registerModule(timeModule)
|
||||
mapper.registerModule(cordaModule)
|
||||
mapper.registerModule(KotlinModule())
|
||||
return mapper
|
||||
val javaTimeModule : Module by lazy {
|
||||
SimpleModule("java.time").apply {
|
||||
addSerializer(LocalDate::class.java, ToStringSerializer)
|
||||
addDeserializer(LocalDate::class.java, LocalDateDeserializer)
|
||||
addKeyDeserializer(LocalDate::class.java, LocalDateKeyDeserializer)
|
||||
addSerializer(LocalDateTime::class.java, ToStringSerializer)
|
||||
}
|
||||
}
|
||||
|
||||
val cordaModule : Module by lazy {
|
||||
SimpleModule("core").apply {
|
||||
addSerializer(Party::class.java, PartySerializer)
|
||||
addDeserializer(Party::class.java, PartyDeserializer)
|
||||
addSerializer(BigDecimal::class.java, ToStringSerializer)
|
||||
addDeserializer(BigDecimal::class.java, NumberDeserializers.BigDecimalDeserializer())
|
||||
addSerializer(SecureHash::class.java, SecureHashSerializer)
|
||||
// It's slightly remarkable, but apparently Jackson works out that this is the only possibility
|
||||
// for a SecureHash at the moment and tries to use SHA256 directly even though we only give it SecureHash
|
||||
addDeserializer(SecureHash.SHA256::class.java, SecureHashDeserializer())
|
||||
addDeserializer(BusinessCalendar::class.java, CalendarDeserializer)
|
||||
|
||||
// For ed25519 pubkeys
|
||||
addSerializer(EdDSAPublicKey::class.java, PublicKeySerializer)
|
||||
addDeserializer(EdDSAPublicKey::class.java, PublicKeyDeserializer)
|
||||
|
||||
// For composite keys
|
||||
addSerializer(CompositeKey::class.java, CompositeKeySerializer)
|
||||
addDeserializer(CompositeKey::class.java, CompositeKeyDeserializer)
|
||||
|
||||
// For NodeInfo
|
||||
// TODO this tunnels the Kryo representation as a Base58 encoded string. Replace when RPC supports this.
|
||||
addSerializer(NodeInfo::class.java, NodeInfoSerializer)
|
||||
addDeserializer(NodeInfo::class.java, NodeInfoDeserializer)
|
||||
}
|
||||
}
|
||||
|
||||
fun createDefaultMapper(identities: IdentityService): ObjectMapper =
|
||||
ServiceHubObjectMapper(identities).apply {
|
||||
enable(SerializationFeature.INDENT_OUTPUT)
|
||||
enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
|
||||
enable(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS)
|
||||
|
||||
registerModule(javaTimeModule)
|
||||
registerModule(cordaModule)
|
||||
registerModule(KotlinModule())
|
||||
}
|
||||
|
||||
class ServiceHubObjectMapper(val identities: IdentityService) : ObjectMapper()
|
||||
|
||||
object ToStringSerializer : JsonSerializer<Any>() {
|
||||
|
@ -42,7 +42,7 @@ configurations {
|
||||
|
||||
dependencies {
|
||||
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||
testCompile group: 'junit', name: 'junit', version: '4.11'
|
||||
testCompile "junit:junit:$junit_version"
|
||||
|
||||
// Corda integration dependencies
|
||||
runtime project(path: ":node:capsule", configuration: 'runtimeArtifacts')
|
||||
@ -127,4 +127,4 @@ task runRecipient(type: JavaExec) {
|
||||
main = 'net.corda.attachmentdemo.AttachmentDemoKt'
|
||||
args '--role'
|
||||
args 'RECIPIENT'
|
||||
}
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ configurations {
|
||||
|
||||
dependencies {
|
||||
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||
testCompile group: 'junit', name: 'junit', version: '4.11'
|
||||
testCompile "junit:junit:$junit_version"
|
||||
|
||||
// Corda integration dependencies
|
||||
runtime project(path: ":node:capsule", configuration: 'runtimeArtifacts')
|
||||
@ -146,4 +146,4 @@ task runWebCashIssue(type: JavaExec) {
|
||||
args 30000
|
||||
args '--currency'
|
||||
args 'GBP'
|
||||
}
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ configurations {
|
||||
|
||||
dependencies {
|
||||
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||
testCompile group: 'junit', name: 'junit', version: '4.11'
|
||||
testCompile "junit:junit:$junit_version"
|
||||
|
||||
// Corda integration dependencies
|
||||
runtime project(path: ":node:capsule", configuration: 'runtimeArtifacts')
|
||||
@ -58,7 +58,7 @@ dependencies {
|
||||
|
||||
// Cordapp dependencies
|
||||
// Specify your cordapp's dependencies below, including dependent cordapps
|
||||
compile 'com.squareup.okhttp3:okhttp:3.3.1'
|
||||
compile "com.squareup.okhttp3:okhttp:$okhttp_version"
|
||||
}
|
||||
|
||||
task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['build']) {
|
||||
@ -129,4 +129,4 @@ publishing {
|
||||
artifact javadocJar
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ class IRSDemoTest: IntegrationTestCategory {
|
||||
|
||||
private fun runDateChange(nodeAddr: HostAndPort) {
|
||||
val url = URL("http://$nodeAddr/api/irs/demodate")
|
||||
assert(putJson(url, "\"2017-01-02\""))
|
||||
assert(putJson(url, "\"2017-06-05\""))
|
||||
}
|
||||
|
||||
private fun runTrade(nodeAddr: HostAndPort) {
|
||||
|
@ -18,7 +18,7 @@ dependencies {
|
||||
compile project(':samples:irs-demo')
|
||||
|
||||
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||
testCompile group: 'junit', name: 'junit', version: '4.11'
|
||||
testCompile "junit:junit:$junit_version"
|
||||
|
||||
// Corda integration dependencies
|
||||
runtime project(path: ":node:capsule", configuration: 'runtimeArtifacts')
|
||||
@ -52,4 +52,4 @@ task deployVisualiser(type: FatCapsule) {
|
||||
minJavaVersion = '1.8.0'
|
||||
javaAgents = [configurations.quasar.singleFile.name]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ configurations {
|
||||
|
||||
dependencies {
|
||||
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||
testCompile group: 'junit', name: 'junit', version: '4.11'
|
||||
testCompile "junit:junit:$junit_version"
|
||||
|
||||
// Corda integration dependencies
|
||||
runtime project(path: ":node:capsule", configuration: 'runtimeArtifacts')
|
||||
|
@ -1,5 +1,5 @@
|
||||
buildscript {
|
||||
ext.strata_version = '1.0.0'
|
||||
ext.strata_version = '1.1.2'
|
||||
}
|
||||
|
||||
apply plugin: 'java'
|
||||
@ -34,11 +34,23 @@ sourceSets {
|
||||
srcDir "../../config/test"
|
||||
}
|
||||
}
|
||||
integrationTest {
|
||||
kotlin {
|
||||
compileClasspath += main.output + test.output
|
||||
runtimeClasspath += main.output + test.output
|
||||
srcDir file('src/integration-test/kotlin')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
configurations {
|
||||
integrationTestCompile.extendsFrom testCompile
|
||||
integrationTestRuntime.extendsFrom testRuntime
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||
testCompile group: 'junit', name: 'junit', version: '4.11'
|
||||
testCompile "junit:junit:$junit_version"
|
||||
|
||||
// Corda integration dependencies
|
||||
runtime project(path: ":node:capsule", configuration: 'runtimeArtifacts')
|
||||
@ -105,6 +117,10 @@ task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['build']) {
|
||||
}
|
||||
}
|
||||
|
||||
task integrationTest(type: Test, dependsOn: []) {
|
||||
testClassesDir = sourceSets.integrationTest.output.classesDir
|
||||
classpath = sourceSets.integrationTest.runtimeClasspath
|
||||
}
|
||||
|
||||
task npmInstall(type: Exec) {
|
||||
workingDir 'src/main/web'
|
||||
|
@ -0,0 +1,78 @@
|
||||
package net.corda.vega
|
||||
|
||||
import com.opengamma.strata.product.common.BuySell
|
||||
import net.corda.core.getOrThrow
|
||||
import net.corda.core.node.services.ServiceInfo
|
||||
import net.corda.node.driver.NodeHandle
|
||||
import net.corda.node.driver.driver
|
||||
import net.corda.node.services.transactions.SimpleNotaryService
|
||||
import net.corda.testing.IntegrationTestCategory
|
||||
import net.corda.testing.getHostAndPort
|
||||
import net.corda.testing.http.HttpApi
|
||||
import net.corda.vega.api.PortfolioApi
|
||||
import net.corda.vega.api.PortfolioApiUtils
|
||||
import net.corda.vega.api.SwapDataModel
|
||||
import net.corda.vega.api.SwapDataView
|
||||
import net.corda.vega.portfolio.Portfolio
|
||||
import org.junit.Test
|
||||
import java.math.BigDecimal
|
||||
import java.time.LocalDate
|
||||
import java.util.*
|
||||
import java.util.concurrent.Future
|
||||
|
||||
class SimmValuationTest: IntegrationTestCategory {
|
||||
private companion object {
|
||||
// SIMM demo can only currently handle one valuation date due to a lack of market data or a market data source.
|
||||
val valuationDate = LocalDate.parse("2016-06-06")
|
||||
val nodeALegalName = "Bank A"
|
||||
val nodeBLegalName = "Bank B"
|
||||
val testTradeId = "trade1"
|
||||
}
|
||||
|
||||
@Test fun `runs SIMM valuation demo`() {
|
||||
driver(isDebug = true) {
|
||||
startNode("Controller", setOf(ServiceInfo(SimpleNotaryService.type))).getOrThrow()
|
||||
val nodeA = getSimmNodeApi(startNode(nodeALegalName))
|
||||
val nodeB = getSimmNodeApi(startNode(nodeBLegalName))
|
||||
val nodeBParty = getPartyWithName(nodeA, nodeBLegalName)
|
||||
val nodeAParty = getPartyWithName(nodeB, nodeALegalName)
|
||||
|
||||
assert(createTradeBetween(nodeA, nodeBParty, testTradeId))
|
||||
assert(tradeExists(nodeB, nodeAParty, testTradeId))
|
||||
assert(runValuationsBetween(nodeA, nodeBParty))
|
||||
assert(valuationExists(nodeB, nodeAParty))
|
||||
}
|
||||
}
|
||||
|
||||
private fun getSimmNodeApi(futureNode: Future<NodeHandle>): HttpApi {
|
||||
val nodeAddr = futureNode.getOrThrow().config.getHostAndPort("webAddress")
|
||||
return HttpApi.fromHostAndPort(nodeAddr, "api/simmvaluationdemo")
|
||||
}
|
||||
|
||||
private fun getPartyWithName(partyApi: HttpApi, countryparty: String): PortfolioApi.ApiParty =
|
||||
getAvailablePartiesFor(partyApi).counterparties.single { it.text == countryparty }
|
||||
|
||||
private fun getAvailablePartiesFor(partyApi: HttpApi): PortfolioApi.AvailableParties {
|
||||
return partyApi.getJson<PortfolioApi.AvailableParties>("whoami")
|
||||
}
|
||||
|
||||
private fun createTradeBetween(partyApi: HttpApi, counterparty: PortfolioApi.ApiParty, tradeId: String): Boolean {
|
||||
val trade = SwapDataModel(tradeId, "desc", valuationDate, "EUR_FIXED_1Y_EURIBOR_3M",
|
||||
valuationDate, LocalDate.parse("2020-01-02"), BuySell.BUY, BigDecimal.valueOf(1000), BigDecimal.valueOf(0.1))
|
||||
return partyApi.putJson("${counterparty.id}/trades", trade)
|
||||
}
|
||||
|
||||
private fun tradeExists(partyApi: HttpApi, counterparty: PortfolioApi.ApiParty, tradeId: String): Boolean {
|
||||
val trades = partyApi.getJson<Array<SwapDataView>>("${counterparty.id}/trades")
|
||||
return (trades.find { it.id == tradeId } != null)
|
||||
}
|
||||
|
||||
private fun runValuationsBetween(partyApi: HttpApi, counterparty: PortfolioApi.ApiParty): Boolean {
|
||||
return partyApi.postJson("${counterparty.id}/portfolio/valuations/calculate", PortfolioApi.ValuationCreationParams(valuationDate))
|
||||
}
|
||||
|
||||
private fun valuationExists(partyApi: HttpApi, counterparty: PortfolioApi.ApiParty): Boolean {
|
||||
val valuations = partyApi.getJson<PortfolioApiUtils.ValuationsView>("${counterparty.id}/portfolio/valuations")
|
||||
return (valuations.initialMargin.call["total"] != 0.0)
|
||||
}
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
package net.corda.vega.api
|
||||
|
||||
/**
|
||||
* A small JSON DSL to create structures for APIs on the fly that mimic JSON in structure.
|
||||
* Use: json { obj("a" to 100, "b" to "hello", "c" to arr(1, 2, "c")) }
|
||||
*/
|
||||
class JsonBuilder {
|
||||
fun obj(vararg objs: Pair<String, Any>): Map<String, Any> {
|
||||
return objs.toMap()
|
||||
}
|
||||
|
||||
fun arr(vararg objs: Any): List<Any> {
|
||||
return objs.toList()
|
||||
}
|
||||
}
|
||||
|
||||
fun json(body: JsonBuilder.() -> Map<String, Any>): Map<String, Any> {
|
||||
val jsonWrapper = JsonBuilder()
|
||||
return jsonWrapper.body()
|
||||
}
|
@ -98,11 +98,9 @@ class PortfolioApi(val rpc: CordaRPCOps) {
|
||||
@Path("business-date")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
fun getBusinessDate(): Any {
|
||||
return json {
|
||||
obj(
|
||||
"business-date" to LocalDateTime.ofInstant(rpc.currentNodeTime(), ZoneId.systemDefault()).toLocalDate()
|
||||
)
|
||||
}
|
||||
return mapOf(
|
||||
"business-date" to LocalDateTime.ofInstant(rpc.currentNodeTime(), ZoneId.systemDefault()).toLocalDate()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -195,12 +193,10 @@ class PortfolioApi(val rpc: CordaRPCOps) {
|
||||
return withParty(partyName) { party ->
|
||||
val trades = getTradesWith(party)
|
||||
val portfolio = Portfolio(trades)
|
||||
val summary = json {
|
||||
obj(
|
||||
"trades" to portfolio.trades.size,
|
||||
"notional" to portfolio.getNotionalForParty(ownParty).toDouble()
|
||||
)
|
||||
}
|
||||
val summary = mapOf(
|
||||
"trades" to portfolio.trades.size,
|
||||
"notional" to portfolio.getNotionalForParty(ownParty).toDouble()
|
||||
)
|
||||
Response.ok().entity(summary).build()
|
||||
}
|
||||
}
|
||||
@ -239,28 +235,23 @@ class PortfolioApi(val rpc: CordaRPCOps) {
|
||||
}
|
||||
}
|
||||
|
||||
data class ApiParty(val id: String, val text: String)
|
||||
data class AvailableParties(val self: ApiParty, val counterparties: List<ApiParty>)
|
||||
|
||||
/**
|
||||
* Returns the identity of the current node as well as a list of other counterparties that it is aware of.
|
||||
*/
|
||||
@GET
|
||||
@Path("whoami")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
fun getWhoAmI(): Any {
|
||||
val counterParties = rpc.networkMapUpdates().first.filter { it.legalIdentity.name != "NetworkMapService" && it.legalIdentity.name != "Notary" && it.legalIdentity.name != ownParty.name }
|
||||
return json {
|
||||
obj(
|
||||
"self" to obj(
|
||||
"id" to ownParty.owningKey.toBase58String(),
|
||||
"text" to ownParty.name
|
||||
),
|
||||
"counterparties" to counterParties.map {
|
||||
obj(
|
||||
"id" to it.legalIdentity.owningKey.toBase58String(),
|
||||
"text" to it.legalIdentity.name
|
||||
)
|
||||
}
|
||||
)
|
||||
fun getWhoAmI(): AvailableParties {
|
||||
val counterParties = rpc.networkMapUpdates().first.filter {
|
||||
it.legalIdentity.name != "NetworkMapService" && it.legalIdentity.name != "Notary" && it.legalIdentity.name != ownParty.name
|
||||
}
|
||||
|
||||
return AvailableParties(
|
||||
self = ApiParty(ownParty.owningKey.toBase58String(), ownParty.name),
|
||||
counterparties = counterParties.map { ApiParty(it.legalIdentity.owningKey.toBase58String(), it.legalIdentity.name) })
|
||||
}
|
||||
|
||||
data class ValuationCreationParams(val valuationDate: LocalDate)
|
||||
|
@ -15,7 +15,16 @@ import java.time.LocalDate
|
||||
* API JSON generation functions for larger JSON outputs.
|
||||
*/
|
||||
class PortfolioApiUtils(private val ownParty: Party) {
|
||||
fun createValuations(state: PortfolioState, portfolio: Portfolio): Any {
|
||||
data class InitialMarginView(val baseCurrency: String, val post: Map<String, Double>, val call: Map<String, Double>, val agreed: Boolean)
|
||||
data class ValuationsView(
|
||||
val businessDate: LocalDate,
|
||||
val portfolio: Map<String, Any>,
|
||||
val marketData: Map<String, Any>,
|
||||
val sensitivities: Map<String, Any>,
|
||||
val initialMargin: InitialMarginView,
|
||||
val confirmation: Map<String, Any>)
|
||||
|
||||
fun createValuations(state: PortfolioState, portfolio: Portfolio): ValuationsView {
|
||||
val valuation = state.valuation!!
|
||||
|
||||
val currency = if (portfolio.trades.isNotEmpty()) {
|
||||
@ -32,141 +41,137 @@ class PortfolioApiUtils(private val ownParty: Party) {
|
||||
|
||||
val completeSubgroups = subgroups.mapValues { it.value.mapValues { it.value[0].third.toDouble() }.toSortedMap() }
|
||||
|
||||
val yieldCurves = json {
|
||||
obj(
|
||||
"name" to "EUR",
|
||||
"values" to completeSubgroups.get("EUR")!!.filter { !it.key.contains("Fixing") }.map {
|
||||
json {
|
||||
obj(
|
||||
"tenor" to it.key,
|
||||
"rate" to it.value
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
val fixings = json {
|
||||
obj(
|
||||
"name" to "EUR",
|
||||
"values" to completeSubgroups.get("EUR")!!.filter { it.key.contains("Fixing") }.map {
|
||||
json {
|
||||
obj(
|
||||
"tenor" to it.key,
|
||||
"rate" to it.value
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
val yieldCurves = mapOf(
|
||||
"name" to "EUR",
|
||||
"values" to completeSubgroups.get("EUR")!!.filter { !it.key.contains("Fixing") }.map {
|
||||
mapOf(
|
||||
"tenor" to it.key,
|
||||
"rate" to it.value
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
val fixings = mapOf(
|
||||
"name" to "EUR",
|
||||
"values" to completeSubgroups.get("EUR")!!.filter { it.key.contains("Fixing") }.map {
|
||||
mapOf(
|
||||
"tenor" to it.key,
|
||||
"rate" to it.value
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
val processedSensitivities = valuation.totalSensivities.sensitivities.map { it.marketDataName to it.parameterMetadata.map { it.label }.zip(it.sensitivity.toList()).toMap() }.toMap()
|
||||
|
||||
return json {
|
||||
obj(
|
||||
"businessDate" to LocalDate.now(),
|
||||
"portfolio" to obj(
|
||||
"trades" to tradeCount,
|
||||
"baseCurrency" to currency,
|
||||
"IRFX" to tradeCount,
|
||||
"commodity" to 0,
|
||||
"equity" to 0,
|
||||
"credit" to 0,
|
||||
"total" to tradeCount,
|
||||
"agreed" to true
|
||||
),
|
||||
"marketData" to obj(
|
||||
"yieldCurves" to yieldCurves,
|
||||
"fixings" to fixings,
|
||||
"agreed" to true
|
||||
),
|
||||
"sensitivities" to obj("curves" to processedSensitivities,
|
||||
"currency" to valuation.currencySensitivies.amounts.toList().map {
|
||||
obj(
|
||||
"currency" to it.currency.code,
|
||||
"amount" to it.amount
|
||||
)
|
||||
},
|
||||
"agreed" to true
|
||||
),
|
||||
"initialMargin" to obj(
|
||||
"baseCurrency" to currency,
|
||||
"post" to obj(
|
||||
"IRFX" to valuation.margin.first,
|
||||
"commodity" to 0,
|
||||
"equity" to 0,
|
||||
"credit" to 0,
|
||||
"total" to valuation.margin.first
|
||||
),
|
||||
"call" to obj(
|
||||
"IRFX" to valuation.margin.first,
|
||||
"commodity" to 0,
|
||||
"equity" to 0,
|
||||
"credit" to 0,
|
||||
"total" to valuation.margin.first
|
||||
),
|
||||
"agreed" to true
|
||||
),
|
||||
"confirmation" to obj(
|
||||
"hash" to state.hash().toString(),
|
||||
"agreed" to true
|
||||
)
|
||||
)
|
||||
}
|
||||
val initialMarginView = InitialMarginView(
|
||||
baseCurrency = currency,
|
||||
post = mapOf(
|
||||
"IRFX" to valuation.margin.first,
|
||||
"commodity" to 0.0,
|
||||
"equity" to 0.0,
|
||||
"credit" to 0.0,
|
||||
"total" to valuation.margin.first
|
||||
),
|
||||
call = mapOf(
|
||||
"IRFX" to valuation.margin.first,
|
||||
"commodity" to 0.0,
|
||||
"equity" to 0.0,
|
||||
"credit" to 0.0,
|
||||
"total" to valuation.margin.first
|
||||
),
|
||||
agreed = true)
|
||||
|
||||
return ValuationsView(
|
||||
businessDate = LocalDate.now(),
|
||||
portfolio = mapOf(
|
||||
"trades" to tradeCount,
|
||||
"baseCurrency" to currency,
|
||||
"IRFX" to tradeCount,
|
||||
"commodity" to 0,
|
||||
"equity" to 0,
|
||||
"credit" to 0,
|
||||
"total" to tradeCount,
|
||||
"agreed" to true
|
||||
),
|
||||
marketData = mapOf(
|
||||
"yieldCurves" to yieldCurves,
|
||||
"fixings" to fixings,
|
||||
"agreed" to true
|
||||
),
|
||||
sensitivities = mapOf("curves" to processedSensitivities,
|
||||
"currency" to valuation.currencySensitivies.amounts.toList().map {
|
||||
mapOf(
|
||||
"currency" to it.currency.code,
|
||||
"amount" to it.amount
|
||||
)
|
||||
},
|
||||
"agreed" to true
|
||||
),
|
||||
initialMargin = initialMarginView,
|
||||
confirmation = mapOf(
|
||||
"hash" to state.hash().toString(),
|
||||
"agreed" to true
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
fun createTradeView(state: IRSState): Any {
|
||||
data class TradeView(
|
||||
val fixedLeg: Map<String, Any>,
|
||||
val floatingLeg: Map<String, Any>,
|
||||
val common: Map<String, Any>,
|
||||
val ref: String)
|
||||
|
||||
fun createTradeView(state: IRSState): TradeView {
|
||||
val trade = if (state.buyer.name == ownParty.name) state.swap.toFloatingLeg() else state.swap.toFloatingLeg()
|
||||
val fixedLeg = trade.product.legs.first { it.type == SwapLegType.FIXED } as RateCalculationSwapLeg
|
||||
val floatingLeg = trade.product.legs.first { it.type != SwapLegType.FIXED } as RateCalculationSwapLeg
|
||||
val fixedRate = fixedLeg.calculation as FixedRateCalculation
|
||||
val floatingRate = floatingLeg.calculation as IborRateCalculation
|
||||
|
||||
return json {
|
||||
obj(
|
||||
"fixedLeg" to obj(
|
||||
"fixedRatePayer" to state.buyer.name,
|
||||
"notional" to obj(
|
||||
"token" to fixedLeg.currency.code,
|
||||
"quantity" to fixedLeg.notionalSchedule.amount.initialValue
|
||||
),
|
||||
"paymentFrequency" to fixedLeg.paymentSchedule.paymentFrequency.toString(),
|
||||
"effectiveDate" to fixedLeg.startDate.unadjusted,
|
||||
"terminationDate" to fixedLeg.endDate.unadjusted,
|
||||
"fixedRate" to obj(
|
||||
"value" to fixedRate.rate.initialValue
|
||||
),
|
||||
"paymentRule" to fixedLeg.paymentSchedule.paymentRelativeTo.name,
|
||||
"calendar" to arr("TODO"),
|
||||
"paymentCalendar" to obj() // TODO
|
||||
),
|
||||
"floatingLeg" to obj(
|
||||
"floatingRatePayer" to state.seller.name,
|
||||
"notional" to obj(
|
||||
"token" to floatingLeg.currency.code,
|
||||
"quantity" to floatingLeg.notionalSchedule.amount.initialValue
|
||||
),
|
||||
"paymentFrequency" to floatingLeg.paymentSchedule.paymentFrequency.toString(),
|
||||
"effectiveDate" to floatingLeg.startDate.unadjusted,
|
||||
"terminationDate" to floatingLeg.endDate.unadjusted,
|
||||
"index" to floatingRate.index.name,
|
||||
"paymentRule" to floatingLeg.paymentSchedule.paymentRelativeTo,
|
||||
"calendar" to arr("TODO"),
|
||||
"paymentCalendar" to arr("TODO"),
|
||||
"fixingCalendar" to obj() // TODO
|
||||
),
|
||||
"common" to obj(
|
||||
"valuationDate" to trade.product.startDate.unadjusted,
|
||||
"hashLegalDocs" to state.contract.legalContractReference.toString(),
|
||||
"interestRate" to obj(
|
||||
"name" to "TODO",
|
||||
"oracle" to "TODO",
|
||||
"tenor" to obj(
|
||||
"name" to "TODO"
|
||||
)
|
||||
)
|
||||
),
|
||||
"ref" to trade.info.id.get().value
|
||||
)
|
||||
}
|
||||
return TradeView(
|
||||
fixedLeg = mapOf(
|
||||
"fixedRatePayer" to state.buyer.name,
|
||||
"notional" to mapOf(
|
||||
"token" to fixedLeg.currency.code,
|
||||
"quantity" to fixedLeg.notionalSchedule.amount.initialValue
|
||||
),
|
||||
"paymentFrequency" to fixedLeg.paymentSchedule.paymentFrequency.toString(),
|
||||
"effectiveDate" to fixedLeg.startDate.unadjusted,
|
||||
"terminationDate" to fixedLeg.endDate.unadjusted,
|
||||
"fixedRate" to mapOf(
|
||||
"value" to fixedRate.rate.initialValue
|
||||
),
|
||||
"paymentRule" to fixedLeg.paymentSchedule.paymentRelativeTo.name,
|
||||
"calendar" to listOf("TODO"),
|
||||
"paymentCalendar" to mapOf<String, Any>() // TODO
|
||||
),
|
||||
floatingLeg = mapOf(
|
||||
"floatingRatePayer" to state.seller.name,
|
||||
"notional" to mapOf(
|
||||
"token" to floatingLeg.currency.code,
|
||||
"quantity" to floatingLeg.notionalSchedule.amount.initialValue
|
||||
),
|
||||
"paymentFrequency" to floatingLeg.paymentSchedule.paymentFrequency.toString(),
|
||||
"effectiveDate" to floatingLeg.startDate.unadjusted,
|
||||
"terminationDate" to floatingLeg.endDate.unadjusted,
|
||||
"index" to floatingRate.index.name,
|
||||
"paymentRule" to floatingLeg.paymentSchedule.paymentRelativeTo,
|
||||
"calendar" to listOf("TODO"),
|
||||
"paymentCalendar" to listOf("TODO"),
|
||||
"fixingCalendar" to mapOf<String, Any>() // TODO
|
||||
),
|
||||
common = mapOf(
|
||||
"valuationDate" to trade.product.startDate.unadjusted,
|
||||
"hashLegalDocs" to state.contract.legalContractReference.toString(),
|
||||
"interestRate" to mapOf(
|
||||
"name" to "TODO",
|
||||
"oracle" to "TODO",
|
||||
"tenor" to mapOf(
|
||||
"name" to "TODO"
|
||||
)
|
||||
)
|
||||
),
|
||||
ref = trade.info.id.get().value
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ configurations {
|
||||
|
||||
dependencies {
|
||||
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||
testCompile group: 'junit', name: 'junit', version: '4.11'
|
||||
testCompile "junit:junit:$junit_version"
|
||||
|
||||
// Corda integration dependencies
|
||||
runtime project(path: ":node:capsule", configuration: 'runtimeArtifacts')
|
||||
@ -145,4 +145,4 @@ task runSeller(type: JavaExec) {
|
||||
main = 'net.corda.traderdemo.TraderDemoKt'
|
||||
args '--role'
|
||||
args 'SELLER'
|
||||
}
|
||||
}
|
||||
|
@ -35,17 +35,17 @@ dependencies {
|
||||
compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
|
||||
compile "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
|
||||
|
||||
compile "com.google.guava:guava:19.0"
|
||||
compile "com.google.guava:guava:$guava_version"
|
||||
|
||||
// Force commons logging to version 1.2 to override Artemis, which pulls in 1.1.3 (ARTEMIS-424)
|
||||
compile "commons-logging:commons-logging:1.2"
|
||||
|
||||
// Unit testing helpers.
|
||||
compile 'junit:junit:4.12'
|
||||
compile "junit:junit:$junit_version"
|
||||
|
||||
// Guava: Google test library (collections test suite)
|
||||
compile "com.google.guava:guava-testlib:19.0"
|
||||
|
||||
// OkHTTP: Simple HTTP library.
|
||||
compile 'com.squareup.okhttp3:okhttp:3.3.1'
|
||||
}
|
||||
compile "com.squareup.okhttp3:okhttp:$okhttp_version"
|
||||
}
|
||||
|
@ -18,7 +18,12 @@ class HttpApi(val root: URL) {
|
||||
*/
|
||||
fun postJson(path: String, data: Any = Unit) = HttpUtils.postJson(URL(root, path), toJson(data))
|
||||
|
||||
private fun toJson(any: Any) = if (any is String) any else ObjectMapper().writeValueAsString(any)
|
||||
/**
|
||||
* Send a GET request to the path on the API specified.
|
||||
*/
|
||||
inline fun<reified T: Any> getJson(path: String, params: Map<String, String> = mapOf()) = HttpUtils.getJson<T>(URL(root, path), params)
|
||||
|
||||
private fun toJson(any: Any) = any as? String ?: HttpUtils.defaultMapper.writeValueAsString(any)
|
||||
|
||||
companion object {
|
||||
fun fromHostAndPort(hostAndPort: HostAndPort, base: String, protocol: String = "http"): HttpApi
|
||||
|
@ -1,6 +1,9 @@
|
||||
package net.corda.testing.http
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper
|
||||
import com.fasterxml.jackson.module.kotlin.KotlinModule
|
||||
import net.corda.core.utilities.loggerFor
|
||||
import net.corda.node.utilities.JsonSupport
|
||||
import okhttp3.*
|
||||
import java.net.URL
|
||||
import java.util.concurrent.TimeUnit
|
||||
@ -15,6 +18,9 @@ object HttpUtils {
|
||||
.connectTimeout(5, TimeUnit.SECONDS)
|
||||
.readTimeout(60, TimeUnit.SECONDS).build()
|
||||
}
|
||||
val defaultMapper: ObjectMapper by lazy {
|
||||
ObjectMapper().registerModule(JsonSupport.javaTimeModule).registerModule(KotlinModule())
|
||||
}
|
||||
|
||||
fun putJson(url: URL, data: String) : Boolean {
|
||||
val body = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), data)
|
||||
@ -26,12 +32,19 @@ object HttpUtils {
|
||||
return makeRequest(Request.Builder().url(url).header("Content-Type", "application/json").post(body).build())
|
||||
}
|
||||
|
||||
inline fun<reified T: Any> getJson(url: URL, params: Map<String, String> = mapOf()) : T {
|
||||
val paramString = if(params.isEmpty()) "" else "?" + params.map { "${it.key}=${it.value}" }.joinToString("&")
|
||||
val parameterisedUrl = URL(url.toExternalForm() + paramString)
|
||||
return defaultMapper.readValue(parameterisedUrl, T::class.java)
|
||||
}
|
||||
|
||||
private fun makeRequest(request: Request): Boolean {
|
||||
val response = client.newCall(request).execute()
|
||||
|
||||
if (!response.isSuccessful) {
|
||||
logger.error("Could not fulfill HTTP request of type ${request.method()} to ${request.url()}. Status Code: ${response.code()}. Message: ${response.body().string()}")
|
||||
}
|
||||
|
||||
return response.isSuccessful
|
||||
}
|
||||
}
|
||||
|
@ -45,10 +45,10 @@ repositories {
|
||||
|
||||
dependencies {
|
||||
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||
testCompile group: 'junit', name: 'junit', version: '4.11'
|
||||
testCompile "junit:junit:$junit_version"
|
||||
|
||||
// TornadoFX: A lightweight Kotlin framework for working with JavaFX UI's.
|
||||
compile 'no.tornado:tornadofx:1.5.7'
|
||||
compile 'no.tornado:tornadofx:1.5.9'
|
||||
|
||||
// Corda Core: Data structures and basic types needed to work with Corda.
|
||||
compile project(':core')
|
||||
@ -57,7 +57,7 @@ dependencies {
|
||||
compile project(':finance')
|
||||
|
||||
// FontAwesomeFX: The "FontAwesome" icon library.
|
||||
compile 'de.jensd:fontawesomefx-fontawesome:4.6.1-2'
|
||||
compile 'de.jensd:fontawesomefx-fontawesome:4.7.0'
|
||||
|
||||
// ReactFX: Functional reactive UI programming.
|
||||
compile 'org.reactfx:reactfx:2.0-M5'
|
||||
@ -86,4 +86,4 @@ task(runSimulationNodes, dependsOn: 'classes', type: JavaExec) {
|
||||
main = 'net.corda.explorer.MainKt'
|
||||
classpath = sourceSets.main.runtimeClasspath
|
||||
args '-S'
|
||||
}
|
||||
}
|
||||
|
@ -35,7 +35,8 @@ dependencies {
|
||||
// https://mvnrepository.com/artifact/de.danielbechler/java-object-diff
|
||||
compile group: 'de.danielbechler', name: 'java-object-diff', version: '0.10.2'
|
||||
|
||||
compile "com.typesafe:config:1.3.0"
|
||||
// TypeSafe Config: for simple and human friendly config files.
|
||||
compile "com.typesafe:config:$typesafe_config_version"
|
||||
}
|
||||
|
||||
run {
|
||||
|
Loading…
x
Reference in New Issue
Block a user