[
  {
    "path": ".gitignore",
    "content": "# Created by .ignore support plugin (hsz.mobi)\n### Java template\n*.class\n\n# Mobile Tools for Java (J2ME)\n.mtj.tmp/\n\n# Package Files #\n*.jar\n*.war\n*.ear\n\n# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml\nhs_err_pid*\n### Gradle template\n.gradle\n/build\nsrc/main/resources/gradle.properties\n\n# Ignore Gradle GUI config\ngradle-app.setting\n\n# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)\n!gradle-wrapper.jar\n\n# Cache of project\n.gradletasknamecache\n\n# Work around https://youtrack.jetbrains.com/issue/IDEA-116898\n# gradle/wrapper/gradle-wrapper.properties\n\n.idea\n*.iml\n\n# OS X\n.DS_Store\n\n# log files\n*.log\nlogs\n/out\n"
  },
  {
    "path": "README.md",
    "content": "# ERC-20 RESTful service\n\nThis application provides a RESTful service for creating and managing \n[ERC-20 tokens](https://github.com/ethereum/EIPs/issues/20). \nIt has been built using [Spring Boot](https://projects.spring.io/spring-boot/), and \n[web3j](https://web3j.io).\n\nIt works with both [Geth](https://github.com/ethereum/go-ethereum), \n[Parity](https://github.com/paritytech/parity), and \n[Quorum](https://github.com/jpmorganchase/quorum).\n\nFor Quorum, the RESTful semantics are identical, with the exception that if you wish to create \na private transaction, you populate a HTTP header name *privateFor* with a comma-separated\nlist of public keys\n\n\n## Build\n\nTo build a runnable jar file:\n\n```bash\n./gradlew clean build\n```\n\n## Run\n\nUsing Java 1.8+:\n\n```bash\njava -jar build/libs/azure-demo-0.1.jar \n```\n\nBy default the application will log to a file named erc20-web3j.log. \n\n\n## Configuration\n\nThe following default properties are used in the application:\n\n```properties\n# Port for service to bind to\nport=8080\n# Log file path and name\nlogging.file=logs/erc20-rest-service.log\n\n# Endpoint of an Ethereum or Quorum node we wish to use. \n# To use IPC simply provide a file path to the socket, such as /path/to/geth.ipc\nnodeEndpoint=http://localhost:22000\n# The Ethereum or Quorum address we wish to use when transacting.\n# Note - this address must be already unlocked in the client\nfromAddress=0xed9d02e382b34818e88b88a309c7fe71e65f419d\n```\n\nYou can override any of these properties by creating a file name \n*application.properties* in the root directory of your application, or in \n*config/application.properties* relative to your root. If you'd rather use yaml, \nsimply change the filename to *application.yml*.\n\n\n## Usage\n\nAll available application endpoints are documented using [Swagger](http://swagger.io/).\n\nYou can view the Swagger UI at http://localhost:8080/swagger-ui.html. From here you\ncan perform all POST and GET requests easily to facilitate deployment of, transacting \nwith, and querying state of ERC-20 tokens.\n\n![alt text](https://github.com/blk-io/erc20-rest-service/raw/master/images/full-swagger-ui.png \"Swagger UI screen capture\")\n\n\n## Docker\n\nWe can use [Docker](https://www.docker.com/) to easily spin up a arbritrary instance \nof our service connecting to an already running Ethereum or Quorum network.\n\nAll you need to do is build the Dockerfile:\n\n```docker\ndocker build -f docker/Dockerfile -t blk-io/erc20-service .\n```\n\nThen either run it with default configuration:\n```docker\ndocker run -p 8080:8080 -v \"$PWD/logs\":/logs blk-io/erc20-service\n```\n \nOr with a custom configuration:\n\n```docker\nexport PORT=8081\ndocker run -p ${PORT}:${PORT} -v \"$PWD/logs\":/logs \\\n    -e ENDPOINT=\"http://localhost:22001\" \\\n    -e FROMADDR=\"0xca843569e3427144cead5e4d5999a3d0ccf92b8e\" \\\n    -e PORT=\"$PORT\" \\\n    blk-io/erc20-service\n```\n"
  },
  {
    "path": "build.gradle",
    "content": "plugins {\n    id 'java'\n    id 'idea'\n    id 'eclipse'\n    id 'application'\n    id 'org.springframework.boot' version '2.1.7.RELEASE'\n}\n\nmainClassName = 'io.blk.erc20.Application'\n\ngroup 'io.blk'\nversion '0.1.0'\n\nsourceCompatibility = 1.8\n\nrepositories {\n    mavenCentral()\n}\n\ndependencies {\n    compile 'org.springframework.boot:spring-boot-starter-web:2.1.7.RELEASE',\n            'io.springfox:springfox-swagger2:2.7.0',\n            'io.springfox:springfox-swagger-ui:2.7.0',\n            'org.projectlombok:lombok:1.16.16',\n            'org.web3j:quorum:4.+',\n            'org.web3j:core:4.+',\n            'io.reactivex.rxjava2:rxjava:2.2.0',\n            'com.fasterxml.jackson:jackson-bom:2.9.4',\n            'org.apache.httpcomponents:httpclient:4.5.3'\n\n    testCompile 'junit:junit:4.12',\n            'org.springframework.boot:spring-boot-starter-test:2.1.7.RELEASE',\n\n\n            implementation(\"org.web3j:contracts:4.2.0\") { exclude group: 'org.web3j' }\n}\n\nrun {\n    /* Can pass all the properties: */\n    systemProperties System.getProperties()\n\n    /* Or just each by name: */\n    systemProperty \"nodeEndpoint\", System.getProperty(\"nodeEndpoint\")\n    systemProperty \"fromAddress\", System.getProperty(\"fromAddress\")\n\n    /* Need to split the space-delimited value in the exec.args */\n    args System.getProperty(\"exec.args\", \"\").split()\n}\n"
  },
  {
    "path": "docker/Dockerfile",
    "content": "FROM frolvlad/alpine-java\n\nRUN apk update && apk upgrade && \\\n    apk add --no-cache bash git openssh\n\nRUN mkdir -p /app/erc20-rest-service\nRUN git clone https://github.com/blk-io/erc20-rest-service.git\n\n# We exclude running tests as we need a Ethereum/Quorum network to be running\nRUN cd erc20-rest-service \\\n  && ./gradlew build -x test \\\n  && cp build/libs/erc20-rest-service-0.1.0.jar /app/erc20-rest-service\n\nENV PORT=8080\nENV ENDPOINT=\"http://localhost:22000\"\nENV FROMADDR=\"0xed9d02e382b34818e88b88a309c7fe71e65f419d\"\n\nENTRYPOINT [\"/usr/bin/java\"]\n# We can define an environment variable to interpolate these values, as Docker does not support\n# this functionality, hence we have to do it in the command.\nCMD [\"-jar\", \"/app/erc20-rest-service/erc20-rest-service-0.1.0.jar\", \\\n  \"--spring.application.json={\\\"nodeEndpoint\\\":\\\"${ENDPOINT}\\\",\\\"fromAddress\\\":\\\"${FROMADDR}\\\"}\"]\n"
  },
  {
    "path": "generate.sh",
    "content": "#!/usr/bin/env bash\n\ncd src/main/resources/solidity/contract/ && \\\n    solc --bin --abi --optimize --overwrite HumanStandardToken.sol -o build/ && \\\n    web3j solidity generate \\\n        --binFile build/HumanStandardToken.bin \\\n        --abiFile build/HumanStandardToken.abi \\\n        -p io.blk.erc20.generated \\\n        -o ../../../java/\n"
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "content": "#Mon Nov 18 15:02:41 GMT 2019\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-5.1.1-all.zip\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStorePath=wrapper/dists\nzipStoreBase=GRADLE_USER_HOME\n"
  },
  {
    "path": "gradlew",
    "content": "#!/usr/bin/env sh\n\n#\n# Copyright 2015 the original author or authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\n##############################################################################\n##\n##  Gradle start up script for UN*X\n##\n##############################################################################\n\n# Attempt to set APP_HOME\n# Resolve links: $0 may be a link\nPRG=\"$0\"\n# Need this for relative symlinks.\nwhile [ -h \"$PRG\" ] ; do\n    ls=`ls -ld \"$PRG\"`\n    link=`expr \"$ls\" : '.*-> \\(.*\\)$'`\n    if expr \"$link\" : '/.*' > /dev/null; then\n        PRG=\"$link\"\n    else\n        PRG=`dirname \"$PRG\"`\"/$link\"\n    fi\ndone\nSAVED=\"`pwd`\"\ncd \"`dirname \\\"$PRG\\\"`/\" >/dev/null\nAPP_HOME=\"`pwd -P`\"\ncd \"$SAVED\" >/dev/null\n\nAPP_NAME=\"Gradle\"\nAPP_BASE_NAME=`basename \"$0\"`\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS='\"-Xmx64m\" \"-Xms64m\"'\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=\"maximum\"\n\nwarn () {\n    echo \"$*\"\n}\n\ndie () {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n}\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\nnonstop=false\ncase \"`uname`\" in\n  CYGWIN* )\n    cygwin=true\n    ;;\n  Darwin* )\n    darwin=true\n    ;;\n  MINGW* )\n    msys=true\n    ;;\n  NONSTOP* )\n    nonstop=true\n    ;;\nesac\n\nCLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=\"$JAVA_HOME/jre/sh/java\"\n    else\n        JAVACMD=\"$JAVA_HOME/bin/java\"\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=\"java\"\n    which java >/dev/null 2>&1 || die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\nfi\n\n# Increase the maximum file descriptors if we can.\nif [ \"$cygwin\" = \"false\" -a \"$darwin\" = \"false\" -a \"$nonstop\" = \"false\" ] ; then\n    MAX_FD_LIMIT=`ulimit -H -n`\n    if [ $? -eq 0 ] ; then\n        if [ \"$MAX_FD\" = \"maximum\" -o \"$MAX_FD\" = \"max\" ] ; then\n            MAX_FD=\"$MAX_FD_LIMIT\"\n        fi\n        ulimit -n $MAX_FD\n        if [ $? -ne 0 ] ; then\n            warn \"Could not set maximum file descriptor limit: $MAX_FD\"\n        fi\n    else\n        warn \"Could not query maximum file descriptor limit: $MAX_FD_LIMIT\"\n    fi\nfi\n\n# For Darwin, add options to specify how the application appears in the dock\nif $darwin; then\n    GRADLE_OPTS=\"$GRADLE_OPTS \\\"-Xdock:name=$APP_NAME\\\" \\\"-Xdock:icon=$APP_HOME/media/gradle.icns\\\"\"\nfi\n\n# For Cygwin or MSYS, switch paths to Windows format before running java\nif [ \"$cygwin\" = \"true\" -o \"$msys\" = \"true\" ] ; then\n    APP_HOME=`cygpath --path --mixed \"$APP_HOME\"`\n    CLASSPATH=`cygpath --path --mixed \"$CLASSPATH\"`\n    JAVACMD=`cygpath --unix \"$JAVACMD\"`\n\n    # We build the pattern for arguments to be converted via cygpath\n    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`\n    SEP=\"\"\n    for dir in $ROOTDIRSRAW ; do\n        ROOTDIRS=\"$ROOTDIRS$SEP$dir\"\n        SEP=\"|\"\n    done\n    OURCYGPATTERN=\"(^($ROOTDIRS))\"\n    # Add a user-defined pattern to the cygpath arguments\n    if [ \"$GRADLE_CYGPATTERN\" != \"\" ] ; then\n        OURCYGPATTERN=\"$OURCYGPATTERN|($GRADLE_CYGPATTERN)\"\n    fi\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    i=0\n    for arg in \"$@\" ; do\n        CHECK=`echo \"$arg\"|egrep -c \"$OURCYGPATTERN\" -`\n        CHECK2=`echo \"$arg\"|egrep -c \"^-\"`                                 ### Determine if an option\n\n        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition\n            eval `echo args$i`=`cygpath --path --ignore --mixed \"$arg\"`\n        else\n            eval `echo args$i`=\"\\\"$arg\\\"\"\n        fi\n        i=$((i+1))\n    done\n    case $i in\n        (0) set -- ;;\n        (1) set -- \"$args0\" ;;\n        (2) set -- \"$args0\" \"$args1\" ;;\n        (3) set -- \"$args0\" \"$args1\" \"$args2\" ;;\n        (4) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" ;;\n        (5) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" ;;\n        (6) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" ;;\n        (7) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" ;;\n        (8) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" ;;\n        (9) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" \"$args8\" ;;\n    esac\nfi\n\n# Escape application args\nsave () {\n    for i do printf %s\\\\n \"$i\" | sed \"s/'/'\\\\\\\\''/g;1s/^/'/;\\$s/\\$/' \\\\\\\\/\" ; done\n    echo \" \"\n}\nAPP_ARGS=$(save \"$@\")\n\n# Collect all arguments for the java command, following the shell quoting and substitution rules\neval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS \"\\\"-Dorg.gradle.appname=$APP_BASE_NAME\\\"\" -classpath \"\\\"$CLASSPATH\\\"\" org.gradle.wrapper.GradleWrapperMain \"$APP_ARGS\"\n\n# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong\nif [ \"$(uname)\" = \"Darwin\" ] && [ \"$HOME\" = \"$PWD\" ]; then\n  cd \"$(dirname \"$0\")\"\nfi\n\nexec \"$JAVACMD\" \"$@\"\n"
  },
  {
    "path": "gradlew.bat",
    "content": "@rem\r\n@rem Copyright 2015 the original author or authors.\r\n@rem\r\n@rem Licensed under the Apache License, Version 2.0 (the \"License\");\r\n@rem you may not use this file except in compliance with the License.\r\n@rem You may obtain a copy of the License at\r\n@rem\r\n@rem      https://www.apache.org/licenses/LICENSE-2.0\r\n@rem\r\n@rem Unless required by applicable law or agreed to in writing, software\r\n@rem distributed under the License is distributed on an \"AS IS\" BASIS,\r\n@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n@rem See the License for the specific language governing permissions and\r\n@rem limitations under the License.\r\n@rem\r\n\r\n@if \"%DEBUG%\" == \"\" @echo off\r\n@rem ##########################################################################\r\n@rem\r\n@rem  Gradle startup script for Windows\r\n@rem\r\n@rem ##########################################################################\r\n\r\n@rem Set local scope for the variables with windows NT shell\r\nif \"%OS%\"==\"Windows_NT\" setlocal\r\n\r\nset DIRNAME=%~dp0\r\nif \"%DIRNAME%\" == \"\" set DIRNAME=.\r\nset APP_BASE_NAME=%~n0\r\nset APP_HOME=%DIRNAME%\r\n\r\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\r\nset DEFAULT_JVM_OPTS=\"-Xmx64m\" \"-Xms64m\"\r\n\r\n@rem Find java.exe\r\nif defined JAVA_HOME goto findJavaFromJavaHome\r\n\r\nset JAVA_EXE=java.exe\r\n%JAVA_EXE% -version >NUL 2>&1\r\nif \"%ERRORLEVEL%\" == \"0\" goto init\r\n\r\necho.\r\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:findJavaFromJavaHome\r\nset JAVA_HOME=%JAVA_HOME:\"=%\r\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\r\n\r\nif exist \"%JAVA_EXE%\" goto init\r\n\r\necho.\r\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:init\r\n@rem Get command-line arguments, handling Windows variants\r\n\r\nif not \"%OS%\" == \"Windows_NT\" goto win9xME_args\r\n\r\n:win9xME_args\r\n@rem Slurp the command line arguments.\r\nset CMD_LINE_ARGS=\r\nset _SKIP=2\r\n\r\n:win9xME_args_slurp\r\nif \"x%~1\" == \"x\" goto execute\r\n\r\nset CMD_LINE_ARGS=%*\r\n\r\n:execute\r\n@rem Setup the command line\r\n\r\nset CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\r\n\r\n@rem Execute Gradle\r\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%\r\n\r\n:end\r\n@rem End local scope for the variables with windows NT shell\r\nif \"%ERRORLEVEL%\"==\"0\" goto mainEnd\r\n\r\n:fail\r\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\r\nrem the _cmd.exe /c_ return code!\r\nif  not \"\" == \"%GRADLE_EXIT_CONSOLE%\" exit 1\r\nexit /b 1\r\n\r\n:mainEnd\r\nif \"%OS%\"==\"Windows_NT\" endlocal\r\n\r\n:omega\r\n"
  },
  {
    "path": "settings.gradle",
    "content": "rootProject.name = 'erc20-rest-service'\n"
  },
  {
    "path": "src/main/java/io/blk/erc20/Application.java",
    "content": "package io.blk.erc20;\n\nimport com.google.common.base.Predicates;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.Banner;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.boot.context.properties.EnableConfigurationProperties;\nimport org.springframework.context.annotation.Bean;\nimport org.web3j.protocol.Web3jService;\nimport org.web3j.protocol.http.HttpService;\nimport org.web3j.protocol.ipc.UnixIpcService;\nimport org.web3j.protocol.ipc.WindowsIpcService;\nimport org.web3j.quorum.Quorum;\nimport springfox.documentation.builders.ApiInfoBuilder;\nimport springfox.documentation.builders.RequestHandlerSelectors;\nimport springfox.documentation.service.ApiInfo;\nimport springfox.documentation.spi.DocumentationType;\nimport springfox.documentation.spring.web.plugins.Docket;\nimport springfox.documentation.swagger2.annotations.EnableSwagger2;\n\n/**\n * Our main application class.\n */\n@EnableSwagger2\n@SpringBootApplication\npublic class Application {\n\n    public static void main(String[] args) {\n        SpringApplication application = new SpringApplication(Application.class);\n        application.setBannerMode(Banner.Mode.OFF);\n        application.run(args);\n    }\n\n    @Autowired\n    NodeConfiguration nodeConfiguration;\n\n    @Bean\n    Quorum quorum() {\n        String nodeEndpoint = nodeConfiguration.getNodeEndpoint();\n        Web3jService web3jService;\n        if (nodeEndpoint == null || nodeEndpoint.equals(\"\")) {\n            web3jService = new HttpService();\n        } else if (nodeEndpoint.startsWith(\"http\")) {\n            web3jService = new HttpService(nodeEndpoint);\n        } else if (System.getProperty(\"os.name\").toLowerCase().startsWith(\"win\")) {\n            web3jService = new WindowsIpcService(nodeEndpoint);\n        } else {\n            web3jService = new UnixIpcService(nodeEndpoint);\n        }\n        return Quorum.build(web3jService);\n    }\n\n    @Bean\n    public Docket lenderApi() {\n        return new Docket(DocumentationType.SWAGGER_2)\n                .apiInfo(apiInfo())\n                .select()\n                // see https://github.com/springfox/springfox/issues/631\n                .apis(Predicates.not(\n                        RequestHandlerSelectors.basePackage(\"org.springframework.boot\")))\n                .build();\n    }\n\n    private ApiInfo apiInfo() {\n        return new ApiInfoBuilder()\n                .title(\"ERC-20 API\")\n                .description(\"ERC-20 token standard RESTful service\")\n                .build();\n    }\n}\n"
  },
  {
    "path": "src/main/java/io/blk/erc20/ContractService.java",
    "content": "package io.blk.erc20;\n\nimport java.math.BigInteger;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.concurrent.ExecutionException;\nimport java.util.function.Function;\n\nimport io.blk.erc20.generated.HumanStandardToken;\nimport io.reactivex.annotations.Nullable;\nimport lombok.Getter;\nimport lombok.Setter;\nimport org.springframework.beans.factory.annotation.Autowired;\n\nimport org.springframework.stereotype.Service;\n\nimport org.web3j.protocol.core.methods.response.TransactionReceipt;\nimport org.web3j.quorum.Quorum;\nimport org.web3j.quorum.tx.ClientTransactionManager;\nimport org.web3j.tx.TransactionManager;\n\nimport static org.web3j.tx.Contract.GAS_LIMIT;\nimport static org.web3j.tx.ManagedTransaction.GAS_PRICE;\n\n/**\n * Our smart contract service.\n */\n@Service\npublic class ContractService {\n\n    private final Quorum quorum;\n\n    private final NodeConfiguration nodeConfiguration;\n\n    @Autowired\n    public ContractService(Quorum quorum, NodeConfiguration nodeConfiguration) {\n        this.quorum = quorum;\n        this.nodeConfiguration = nodeConfiguration;\n    }\n\n    public NodeConfiguration getConfig() {\n        return nodeConfiguration;\n    }\n\n    public String deploy(\n            List<String> privateFor, BigInteger initialAmount, String tokenName, BigInteger decimalUnits,\n            String tokenSymbol) throws Exception {\n        try {\n            TransactionManager transactionManager = new ClientTransactionManager(\n                    quorum, nodeConfiguration.getFromAddress(), privateFor);\n            HumanStandardToken humanStandardToken = HumanStandardToken.deploy(\n                    quorum, transactionManager, GAS_PRICE, GAS_LIMIT,\n                    initialAmount, tokenName, decimalUnits,\n                    tokenSymbol).send();\n            return humanStandardToken.getContractAddress();\n        } catch (InterruptedException | ExecutionException e) {\n            throw new RuntimeException(e);\n        }\n    }\n\n    public String name(String contractAddress) throws Exception {\n        HumanStandardToken humanStandardToken = load(contractAddress);\n        try {\n            return humanStandardToken.name().send();\n        } catch (InterruptedException | ExecutionException e) {\n            throw new RuntimeException(e);\n        }\n    }\n\n    public TransactionResponse<ApprovalEventResponse> approve(\n            List<String> privateFor, String contractAddress, String spender, BigInteger value) throws Exception {\n        HumanStandardToken humanStandardToken = load(contractAddress, privateFor);\n        try {\n            TransactionReceipt transactionReceipt = humanStandardToken\n                    .approve(spender, value).send();\n            return processApprovalEventResponse(humanStandardToken, transactionReceipt);\n        } catch (InterruptedException | ExecutionException e) {\n            throw new RuntimeException(e);\n        }\n    }\n\n    public String totalSupply(String contractAddress) throws Exception {\n        HumanStandardToken humanStandardToken = load(contractAddress);\n        try {\n            return humanStandardToken.totalSupply().send().toString();\n        } catch (InterruptedException | ExecutionException e) {\n            throw new RuntimeException(e);\n        }\n    }\n\n    public TransactionResponse<TransferEventResponse> transferFrom(\n            List<String> privateFor, String contractAddress, String from, String to, BigInteger value) throws Exception {\n        HumanStandardToken humanStandardToken = load(contractAddress, privateFor);\n        try {\n            TransactionReceipt transactionReceipt = humanStandardToken\n                    .transferFrom(from, to, value).send();\n            return processTransferEventsResponse(humanStandardToken, transactionReceipt);\n        } catch (InterruptedException | ExecutionException e) {\n            throw new RuntimeException(e);\n        }\n    }\n\n    public String decimals(String contractAddress) throws Exception {\n        HumanStandardToken humanStandardToken = load(contractAddress);\n        try {\n            return humanStandardToken.decimals().send().toString();\n        } catch (InterruptedException | ExecutionException e) {\n            throw new RuntimeException(e);\n        }\n    }\n\n    public String version(String contractAddress) throws Exception {\n        HumanStandardToken humanStandardToken = load(contractAddress);\n        try {\n            return humanStandardToken.version().send();\n        } catch (InterruptedException | ExecutionException e) {\n            throw new RuntimeException(e);\n        }\n    }\n\n    public String balanceOf(String contractAddress, String ownerAddress) throws Exception {\n        HumanStandardToken humanStandardToken = load(contractAddress);\n        try {\n            return humanStandardToken.balanceOf(ownerAddress).send().toString();\n        } catch (InterruptedException | ExecutionException e) {\n            throw new RuntimeException(e);\n        }\n    }\n\n    public String symbol(String contractAddress) throws Exception {\n        HumanStandardToken humanStandardToken = load(contractAddress);\n        try {\n            return humanStandardToken.symbol().send();\n        } catch (InterruptedException | ExecutionException e) {\n            throw new RuntimeException(e);\n        }\n    }\n\n    public TransactionResponse<TransferEventResponse> transfer(\n            List<String> privateFor, String contractAddress, String to, BigInteger value) throws Exception {\n        HumanStandardToken humanStandardToken = load(contractAddress, privateFor);\n        try {\n            TransactionReceipt transactionReceipt = humanStandardToken\n                    .transfer(to, value).send();\n            return processTransferEventsResponse(humanStandardToken, transactionReceipt);\n        } catch (InterruptedException | ExecutionException e) {\n            throw new RuntimeException(e);\n        }\n    }\n\n    public TransactionResponse<ApprovalEventResponse> approveAndCall(\n            @Nullable List<String> privateFor, String contractAddress, String spender, BigInteger value,\n            String extraData) throws Exception {\n        HumanStandardToken humanStandardToken = load(contractAddress, privateFor);\n        try {\n            TransactionReceipt transactionReceipt = humanStandardToken\n                    .approveAndCall(\n                            spender, value,\n                            extraData.getBytes())\n                    .send();\n            return processApprovalEventResponse(humanStandardToken, transactionReceipt);\n        } catch (InterruptedException | ExecutionException e) {\n            throw new RuntimeException(e);\n        }\n    }\n\n    public String allowance(String contractAddress, String ownerAddress, String spenderAddress) throws Exception {\n        HumanStandardToken humanStandardToken = load(contractAddress);\n        try {\n            return humanStandardToken.allowance(\n                    ownerAddress, spenderAddress)\n                    .send().toString();\n        } catch (InterruptedException | ExecutionException e) {\n            throw new RuntimeException(e);\n        }\n    }\n\n    private HumanStandardToken load(String contractAddress, List<String> privateFor) {\n        TransactionManager transactionManager = new ClientTransactionManager(\n                quorum, nodeConfiguration.getFromAddress(), privateFor);\n        return HumanStandardToken.load(\n                contractAddress, quorum, transactionManager, GAS_PRICE, GAS_LIMIT);\n    }\n\n    private HumanStandardToken load(String contractAddress) {\n        TransactionManager transactionManager = new ClientTransactionManager(\n                quorum, nodeConfiguration.getFromAddress(), Collections.emptyList());\n        return HumanStandardToken.load(\n                contractAddress, quorum, transactionManager, GAS_PRICE, GAS_LIMIT);\n    }\n\n    private TransactionResponse<ApprovalEventResponse>\n            processApprovalEventResponse(\n            HumanStandardToken humanStandardToken,\n            TransactionReceipt transactionReceipt) {\n\n        return processEventResponse(\n                humanStandardToken.getApprovalEvents(transactionReceipt),\n                transactionReceipt,\n                ApprovalEventResponse::new);\n    }\n\n    private TransactionResponse<TransferEventResponse>\n            processTransferEventsResponse(\n            HumanStandardToken humanStandardToken,\n            TransactionReceipt transactionReceipt) {\n\n        return processEventResponse(\n                humanStandardToken.getTransferEvents(transactionReceipt),\n                transactionReceipt,\n                TransferEventResponse::new);\n    }\n\n    private <T, R> TransactionResponse<R> processEventResponse(\n            List<T> eventResponses, TransactionReceipt transactionReceipt, Function<T, R> map) {\n        if (!eventResponses.isEmpty()) {\n            return new TransactionResponse<>(\n                    transactionReceipt.getTransactionHash(),\n                    map.apply(eventResponses.get(0)));\n        } else {\n            return new TransactionResponse<>(\n                    transactionReceipt.getTransactionHash());\n        }\n    }\n\n    @Getter\n    @Setter\n    public static class TransferEventResponse {\n        private String from;\n        private String to;\n        private long value;\n\n        public TransferEventResponse() { }\n\n        public TransferEventResponse(\n                HumanStandardToken.TransferEventResponse transferEventResponse) {\n            this.from = transferEventResponse._from;\n            this.to = transferEventResponse._to;\n            this.value = transferEventResponse._value.longValueExact();\n        }\n\n        public String getFrom() {\n            return from;\n        }\n\n        public void setFrom(String from) {\n            this.from = from;\n        }\n\n        public String getTo() {\n            return to;\n        }\n\n        public void setTo(String to) {\n            this.to = to;\n        }\n\n        public long getValue() {\n            return value;\n        }\n\n        public void setValue(long value) {\n            this.value = value;\n        }\n    }\n\n    @Getter\n    @Setter\n    public static class ApprovalEventResponse {\n        private String owner;\n        private String spender;\n        private long value;\n\n        public ApprovalEventResponse() { }\n\n        public ApprovalEventResponse(\n                HumanStandardToken.ApprovalEventResponse approvalEventResponse) {\n            this.owner = approvalEventResponse._owner;\n            this.spender = approvalEventResponse._spender;\n            this.value = approvalEventResponse._value.longValueExact();\n        }\n\n        public String getOwner() {\n            return owner;\n        }\n\n        public void setOwner(String owner) {\n            this.owner = owner;\n        }\n\n        public String getSpender() {\n            return spender;\n        }\n\n        public void setSpender(String spender) {\n            this.spender = spender;\n        }\n\n        public long getValue() {\n            return value;\n        }\n\n        public void setValue(long value) {\n            this.value = value;\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/io/blk/erc20/Controller.java",
    "content": "package io.blk.erc20;\n\nimport java.math.BigInteger;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.List;\nimport javax.servlet.http.HttpServletRequest;\n\nimport io.reactivex.annotations.Nullable;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiImplicitParam;\nimport io.swagger.annotations.ApiOperation;\nimport lombok.Data;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.http.MediaType;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.RequestBody;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.RestController;\n\n/**\n * Controller for our ERC-20 contract API.\n */\n@Api(\"ERC-20 token standard API\")\n@RestController\npublic class Controller {\n\n    private final ContractService ContractService;\n\n    @Autowired\n    public Controller(ContractService ContractService) {\n        this.ContractService = ContractService;\n    }\n\n    @ApiOperation(\"Application configuration\")\n    @RequestMapping(value = \"/config\", method = RequestMethod.GET,\n            produces = MediaType.APPLICATION_JSON_UTF8_VALUE)\n    NodeConfiguration config() {\n        return ContractService.getConfig();\n    }\n\n    @ApiOperation(\n            value = \"Deploy new ERC-20 token\",\n            notes = \"Returns hex encoded contract address\")\n    @ApiImplicitParam(name = \"privateFor\",\n            value = \"Comma separated list of public keys of enclave nodes that transaction is \"\n                    + \"private for\",\n            paramType = \"header\",\n            dataType = \"string\")\n    @RequestMapping(value = \"/deploy\", method = RequestMethod.POST)\n    String deploy(\n            HttpServletRequest request,\n            @RequestBody ContractSpecification contractSpecification) throws Exception {\n\n        return ContractService.deploy(\n                extractPrivateFor(request),\n                contractSpecification.getInitialAmount(),\n                contractSpecification.getTokenName(),\n                contractSpecification.getDecimalUnits(),\n                contractSpecification.getTokenSymbol());\n    }\n\n    @ApiOperation(\"Get token name\")\n    @RequestMapping(value = \"/{contractAddress}/name\", method = RequestMethod.GET)\n    String name(@PathVariable String contractAddress) throws Exception {\n        return ContractService.name(contractAddress);\n    }\n\n    @ApiOperation(\n            value = \"Approve transfers by a specific address up to the provided total quantity\",\n            notes = \"Returns hex encoded transaction hash, and Approval event if called\")\n    @ApiImplicitParam(name = \"privateFor\",\n            value = \"Comma separated list of public keys of enclave nodes that transaction is \"\n                    + \"private for\",\n            paramType = \"header\",\n            dataType = \"string\")\n    @RequestMapping(value = \"/{contractAddress}/approve\", method = RequestMethod.POST)\n    TransactionResponse<ContractService.ApprovalEventResponse> approve(\n            HttpServletRequest request,\n            @PathVariable String contractAddress,\n            @RequestBody ApproveRequest approveRequest) throws Exception {\n        return ContractService.approve(\n                extractPrivateFor(request),\n                contractAddress,\n                approveRequest.getSpender(),\n                approveRequest.getValue());\n    }\n\n    @ApiOperation(\"Get total supply of tokens\")\n    @RequestMapping(value = \"/{contractAddress}/totalSupply\", method = RequestMethod.GET)\n    String totalSupply(@PathVariable String contractAddress) throws Exception {\n        return ContractService.totalSupply(contractAddress);\n    }\n\n    @ApiOperation(\n            value = \"Transfer tokens between addresses (must already be approved)\",\n            notes = \"Returns hex encoded transaction hash, and Transfer event if called\")\n    @ApiImplicitParam(name = \"privateFor\",\n            value = \"Comma separated list of public keys of enclave nodes that transaction is \"\n                    + \"private for\",\n            paramType = \"header\",\n            dataType = \"string\")\n    @RequestMapping(value = \"/{contractAddress}/transferFrom\", method = RequestMethod.POST)\n    TransactionResponse<ContractService.TransferEventResponse> transferFrom(\n            HttpServletRequest request,\n            @PathVariable String contractAddress,\n            @RequestBody TransferFromRequest transferFromRequest) throws Exception {\n        return ContractService.transferFrom(\n                extractPrivateFor(request),\n                contractAddress,\n                transferFromRequest.getFrom(),\n                transferFromRequest.getTo(),\n                transferFromRequest.getValue());\n    }\n\n    @ApiOperation(\"Get decimal precision of tokens\")\n    @RequestMapping(value = \"/{contractAddress}/decimals\", method = RequestMethod.GET)\n    String decimals(@PathVariable String contractAddress) throws Exception {\n        return ContractService.decimals(contractAddress);\n    }\n\n    @ApiOperation(\"Get contract version\")\n    @RequestMapping(value = \"/{contractAddress}/version\", method = RequestMethod.GET)\n    String version(@PathVariable String contractAddress) throws Exception {\n        return ContractService.version(contractAddress);\n    }\n\n    @ApiOperation(\"Get token balance for address\")\n    @RequestMapping(\n            value = \"/{contractAddress}/balanceOf/{ownerAddress}\", method = RequestMethod.GET)\n    String balanceOf(\n            @PathVariable String contractAddress,\n            @PathVariable String ownerAddress) throws Exception {\n        return ContractService.balanceOf(contractAddress, ownerAddress);\n    }\n\n    @ApiOperation(\"Get token symbol\")\n    @RequestMapping(value = \"/{contractAddress}/symbol\", method = RequestMethod.GET)\n    String symbol(@PathVariable String contractAddress) throws Exception {\n        return ContractService.symbol(contractAddress);\n    }\n\n    @ApiOperation(\n            value = \"Transfer tokens you own to another address\",\n            notes = \"Returns hex encoded transaction hash, and Transfer event if called\")\n    @ApiImplicitParam(name = \"privateFor\",\n            value = \"Comma separated list of public keys of enclave nodes that transaction is \"\n                    + \"private for\",\n            paramType = \"header\",\n            dataType = \"string\")\n    @RequestMapping(value = \"/{contractAddress}/transfer\", method = RequestMethod.POST)\n    TransactionResponse<ContractService.TransferEventResponse> transfer(\n            HttpServletRequest request,\n            @PathVariable String contractAddress,\n            @RequestBody TransferRequest transferRequest) throws Exception {\n        return ContractService.transfer(\n                extractPrivateFor(request),\n                contractAddress,\n                transferRequest.getTo(),\n                transferRequest.getValue());\n    }\n\n    @ApiOperation(\n            value = \"Approve transfers by a specific contract address up to the provided total \"\n                    + \"quantity, and notify that contract address of the approval\",\n            notes = \"Returns hex encoded transaction hash, and Approval event if called\")\n    @ApiImplicitParam(name = \"privateFor\",\n            value = \"Comma separated list of public keys of enclave nodes that transaction is \"\n                    + \"private for\",\n            paramType = \"header\",\n            dataType = \"string\")\n    @RequestMapping(value = \"/{contractAddress}/approveAndCall\", method = RequestMethod.POST)\n    TransactionResponse<ContractService.ApprovalEventResponse> approveAndCall(\n            HttpServletRequest request,\n            @PathVariable String contractAddress,\n            @RequestBody ApproveAndCallRequest approveAndCallRequest) throws Exception {\n        return ContractService.approveAndCall(\n                extractPrivateFor(request),\n                contractAddress,\n                approveAndCallRequest.getSpender(),\n                approveAndCallRequest.getValue(),\n                approveAndCallRequest.getExtraData());\n    }\n\n    @ApiOperation(\"Get quantity of tokens you can transfer on another token holder's behalf\")\n    @RequestMapping(value = \"/{contractAddress}/allowance\", method = RequestMethod.GET)\n    String allowance(\n            @PathVariable String contractAddress,\n            @RequestParam String ownerAddress,\n            @RequestParam String spenderAddress) throws Exception {\n        return ContractService.allowance(\n                contractAddress, ownerAddress, spenderAddress);\n    }\n\n    private static @Nullable List<String> extractPrivateFor(HttpServletRequest request) {\n        String privateFor = request.getHeader(\"privateFor\");\n        if (privateFor == null) {\n            return null;\n        } else {\n            return Arrays.asList(privateFor.split(\",\"));\n        }\n    }\n\n    @Data\n    static class ContractSpecification {\n        private  BigInteger initialAmount;\n        private  String tokenName;\n        private  BigInteger decimalUnits;\n        private  String tokenSymbol;\n\n        ContractSpecification() {\n        }\n\n        ContractSpecification(BigInteger initialAmount, String tokenName, BigInteger decimalUnits, String tokenSymbol) {\n            this.initialAmount = initialAmount;\n            this.tokenName = tokenName;\n            this.decimalUnits = decimalUnits;\n            this.tokenSymbol = tokenSymbol;\n        }\n\n        public BigInteger getDecimalUnits() {\n            return decimalUnits;\n        }\n\n        public BigInteger getInitialAmount() {\n            return initialAmount;\n        }\n\n        public String getTokenName() {\n            return tokenName;\n        }\n\n        public String getTokenSymbol() {\n            return tokenSymbol;\n        }\n    }\n\n    @Data\n    static class ApproveRequest {\n        private String spender;\n        private BigInteger value;\n\n        ApproveRequest() {}\n\n        ApproveRequest(String spender, BigInteger value) {\n            this.spender = spender;\n            this.value = value;\n        }\n\n        public String getSpender() {\n            return spender;\n        }\n\n        public BigInteger getValue() {\n            return value;\n        }\n    }\n\n    @Data\n    static class TransferFromRequest {\n        private String from;\n        private String to;\n        private BigInteger value;\n\n        TransferFromRequest() {}\n\n        TransferFromRequest(String from, String to, BigInteger value) {\n            this.from = from;\n            this.to = to;\n            this.value = value;\n        }\n\n\n        public String getFrom() {\n            return from;\n        }\n\n        BigInteger getValue() {\n            return value;\n        }\n\n        public String getTo() {\n            return to;\n        }\n    }\n\n    @Data\n    static class TransferRequest {\n        private String to;\n        private BigInteger value;\n\n        TransferRequest(String to, BigInteger value) {\n            this.to = to;\n            this.value = value;\n        }\n\n        TransferRequest() {}\n\n        public String getTo() {\n            return to;\n        }\n\n        public BigInteger getValue() {\n            return value;\n        }\n    }\n\n    @Data\n    static class ApproveAndCallRequest {\n        private String spender;\n        private BigInteger value;\n        private String extraData;\n\n        ApproveAndCallRequest() {}\n\n        ApproveAndCallRequest(String spender, BigInteger value, String extraData) {\n            this.spender = spender;\n            this.value = value;\n            this.extraData = extraData;\n        }\n\n        String getSpender() {\n            return spender;\n        }\n\n        BigInteger getValue() {\n            return value;\n        }\n\n        String getExtraData() {\n            return extraData;\n        }\n    }\n\n    @Data\n    static class AllowanceRequest {\n        private String ownerAddress;\n        private String spenderAddress;\n\n        AllowanceRequest() {}\n\n        AllowanceRequest(String ownerAddress, String spenderAddress) {\n            this.ownerAddress = ownerAddress;\n            this.spenderAddress = spenderAddress;\n        }\n\n        public String getOwnerAddress() {\n            return ownerAddress;\n        }\n\n        public void setOwnerAddress(String ownerAddress) {\n            this.ownerAddress = ownerAddress;\n        }\n\n        public String getSpenderAddress() {\n            return spenderAddress;\n        }\n\n        public void setSpenderAddress(String spenderAddress) {\n            this.spenderAddress = spenderAddress;\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/io/blk/erc20/NodeConfiguration.java",
    "content": "package io.blk.erc20;\n\nimport lombok.Data;\nimport org.springframework.boot.context.properties.ConfigurationProperties;\nimport org.springframework.stereotype.Component;\n\n/**\n * Node configuration bean.\n */\n@Data\n@ConfigurationProperties(\"io.blk.erc20\")\n@Component\npublic class NodeConfiguration {\n\n    private String nodeEndpoint = System.getProperty(\"nodeEndpoint\");\n    private String fromAddress = System.getProperty(\"fromAddress\");\n\n    public String getNodeEndpoint() {\n        return nodeEndpoint;\n    }\n\n    public void setNodeEndpoint(String nodeEndpoint) {\n        this.nodeEndpoint = nodeEndpoint;\n    }\n\n    public String getFromAddress() {\n        return fromAddress;\n    }\n\n    public void setFromAddress(String fromAddress) {\n        this.fromAddress = fromAddress;\n    }\n}\n"
  },
  {
    "path": "src/main/java/io/blk/erc20/TransactionResponse.java",
    "content": "package io.blk.erc20;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\n/**\n * TransactionResponse wrapper.\n */\n@Getter\n@Setter\npublic class TransactionResponse<T> {\n\n    private String transactionHash;\n    private T event;\n\n    TransactionResponse() { }\n\n    public TransactionResponse(String transactionHash) {\n        this(transactionHash, null);\n    }\n\n    public TransactionResponse(String transactionHash, T event) {\n        this.transactionHash = transactionHash;\n        this.event = event;\n    }\n\n    public String getTransactionHash() {\n        return transactionHash;\n    }\n\n    public void setTransactionHash(String transactionHash) {\n        this.transactionHash = transactionHash;\n    }\n\n    public T getEvent() {\n        return event;\n    }\n\n    public void setEvent(T event) {\n        this.event = event;\n    }\n}\n"
  },
  {
    "path": "src/main/java/io/blk/erc20/generated/HumanStandardToken.java",
    "content": "package io.blk.erc20.generated;\n\nimport io.reactivex.Flowable;\nimport java.math.BigInteger;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.List;\nimport org.web3j.abi.EventEncoder;\nimport org.web3j.abi.FunctionEncoder;\nimport org.web3j.abi.TypeReference;\nimport org.web3j.abi.datatypes.Address;\nimport org.web3j.abi.datatypes.Event;\nimport org.web3j.abi.datatypes.Function;\nimport org.web3j.abi.datatypes.Type;\nimport org.web3j.abi.datatypes.Utf8String;\nimport org.web3j.abi.datatypes.generated.Uint256;\nimport org.web3j.abi.datatypes.generated.Uint8;\nimport org.web3j.crypto.Credentials;\nimport org.web3j.protocol.Web3j;\nimport org.web3j.protocol.core.DefaultBlockParameter;\nimport org.web3j.protocol.core.RemoteCall;\nimport org.web3j.protocol.core.methods.request.EthFilter;\nimport org.web3j.protocol.core.methods.response.Log;\nimport org.web3j.protocol.core.methods.response.TransactionReceipt;\nimport org.web3j.tx.Contract;\nimport org.web3j.tx.TransactionManager;\nimport org.web3j.tx.gas.ContractGasProvider;\n\n/**\n * <p>Auto generated code.\n * <p><strong>Do not modify!</strong>\n * <p>Please use the <a href=\"https://docs.web3j.io/command_line.html\">web3j command line tools</a>,\n * or the org.web3j.codegen.SolidityFunctionWrapperGenerator in the \n * <a href=\"https://github.com/web3j/web3j/tree/master/codegen\">codegen module</a> to update.\n *\n * <p>Generated with web3j version 4.3.0.\n */\npublic class HumanStandardToken extends Contract {\n    private static final String BINARY = \"60c0604052600460808190527f48302e310000000000000000000000000000000000000000000000000000000060a090815261003e916006919061016b565b5034801561004b57600080fd5b50604051610a4f380380610a4f8339810180604052608081101561006e57600080fd5b81516020830180519193928301929164010000000081111561008f57600080fd5b820160208101848111156100a257600080fd5b81516401000000008111828201871017156100bc57600080fd5b505060208201516040909201805191949293916401000000008111156100e157600080fd5b820160208101848111156100f457600080fd5b815164010000000081118282018710171561010e57600080fd5b5050336000908152600160209081526040822089905590889055865191945061013e93506003925086019061016b565b506004805460ff191660ff8416179055805161016190600590602084019061016b565b5050505050610206565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106101ac57805160ff19168380011785556101d9565b828001600101855582156101d9579182015b828111156101d95782518255916020019190600101906101be565b506101e59291506101e9565b5090565b61020391905b808211156101e557600081556001016101ef565b90565b61083a806102156000396000f3fe608060405234801561001057600080fd5b50600436106100c6576000357c01000000000000000000000000000000000000000000000000000000009004806354fd4d501161008e57806354fd4d50146101f657806370a08231146101fe57806395d89b4114610224578063a9059cbb1461022c578063cae9ca5114610258578063dd62ed3e146102dd576100c6565b806306fdde03146100cb578063095ea7b31461014857806318160ddd1461018857806323b872dd146101a2578063313ce567146101d8575b600080fd5b6100d361030b565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561010d5781810151838201526020016100f5565b50505050905090810190601f16801561013a5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6101746004803603604081101561015e57600080fd5b50600160a060020a038135169060200135610399565b604080519115158252519081900360200190f35b610190610400565b60408051918252519081900360200190f35b610174600480360360608110156101b857600080fd5b50600160a060020a03813581169160208101359091169060400135610406565b6101e06104f3565b6040805160ff9092168252519081900360200190f35b6100d36104fc565b6101906004803603602081101561021457600080fd5b5035600160a060020a0316610557565b6100d3610572565b6101746004803603604081101561024257600080fd5b50600160a060020a0381351690602001356105cd565b6101746004803603606081101561026e57600080fd5b600160a060020a038235169160208101359181019060608101604082013564010000000081111561029e57600080fd5b8201836020820111156102b057600080fd5b803590602001918460018302840111640100000000831117156102d257600080fd5b509092509050610666565b610190600480360360408110156102f357600080fd5b50600160a060020a03813581169160200135166107b5565b6003805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156103915780601f1061036657610100808354040283529160200191610391565b820191906000526020600020905b81548152906001019060200180831161037457829003601f168201915b505050505081565b336000818152600260209081526040808320600160a060020a038716808552908352818420869055815186815291519394909390927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925928290030190a35060015b92915050565b60005481565b600160a060020a03831660009081526001602052604081205482118015906104515750600160a060020a03841660009081526002602090815260408083203384529091529020548211155b801561045d5750600082115b156104e857600160a060020a03808416600081815260016020908152604080832080548801905593881680835284832080548890039055600282528483203384528252918490208054879003905583518681529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35060016104ec565b5060005b9392505050565b60045460ff1681565b6006805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156103915780601f1061036657610100808354040283529160200191610391565b600160a060020a031660009081526001602052604090205490565b6005805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156103915780601f1061036657610100808354040283529160200191610391565b3360009081526001602052604081205482118015906105ec5750600082115b1561065e5733600081815260016020908152604080832080548790039055600160a060020a03871680845292819020805487019055805186815290519293927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929181900390910190a35060016103fa565b5060006103fa565b336000818152600260209081526040808320600160a060020a038916808552908352818420889055815188815291519394909390927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925928290030190a3600085600160a060020a031660405160200180806020018281038252602e8152602001806107e1602e91396040019150506040516020818303038152906040526040518082805190602001908083835b602083106107325780518252601f199092019160209182019101610713565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114610794576040519150601f19603f3d011682016040523d82523d6000602084013e610799565b606091505b505090508015156107a957600080fd5b50600195945050505050565b600160a060020a0391821660009081526002602090815260408083209390941682529190915220549056fe72656365697665417070726f76616c28616464726573732c75696e743235362c616464726573732c627974657329a165627a7a72305820d15a070a95051e159632a5f42da17cdc0b4e940c8c7574a86370e2f434405abd0029\";\n\n    public static final String FUNC_NAME = \"name\";\n\n    public static final String FUNC_APPROVE = \"approve\";\n\n    public static final String FUNC_TOTALSUPPLY = \"totalSupply\";\n\n    public static final String FUNC_TRANSFERFROM = \"transferFrom\";\n\n    public static final String FUNC_DECIMALS = \"decimals\";\n\n    public static final String FUNC_VERSION = \"version\";\n\n    public static final String FUNC_BALANCEOF = \"balanceOf\";\n\n    public static final String FUNC_SYMBOL = \"symbol\";\n\n    public static final String FUNC_TRANSFER = \"transfer\";\n\n    public static final String FUNC_APPROVEANDCALL = \"approveAndCall\";\n\n    public static final String FUNC_ALLOWANCE = \"allowance\";\n\n    public static final Event TRANSFER_EVENT = new Event(\"Transfer\", \n            Arrays.<TypeReference<?>>asList(new TypeReference<Address>(true) {}, new TypeReference<Address>(true) {}, new TypeReference<Uint256>() {}));\n    ;\n\n    public static final Event APPROVAL_EVENT = new Event(\"Approval\", \n            Arrays.<TypeReference<?>>asList(new TypeReference<Address>(true) {}, new TypeReference<Address>(true) {}, new TypeReference<Uint256>() {}));\n    ;\n\n    @Deprecated\n    protected HumanStandardToken(String contractAddress, Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) {\n        super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit);\n    }\n\n    protected HumanStandardToken(String contractAddress, Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) {\n        super(BINARY, contractAddress, web3j, credentials, contractGasProvider);\n    }\n\n    @Deprecated\n    protected HumanStandardToken(String contractAddress, Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) {\n        super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit);\n    }\n\n    protected HumanStandardToken(String contractAddress, Web3j web3j, TransactionManager transactionManager, ContractGasProvider contractGasProvider) {\n        super(BINARY, contractAddress, web3j, transactionManager, contractGasProvider);\n    }\n\n    public RemoteCall<String> name() {\n        final Function function = new Function(FUNC_NAME, \n                Arrays.<Type>asList(), \n                Arrays.<TypeReference<?>>asList(new TypeReference<Utf8String>() {}));\n        return executeRemoteCallSingleValueReturn(function, String.class);\n    }\n\n    public RemoteCall<TransactionReceipt> approve(String _spender, BigInteger _value) {\n        final Function function = new Function(\n                FUNC_APPROVE, \n                Arrays.<Type>asList(new org.web3j.abi.datatypes.Address(_spender), \n                new org.web3j.abi.datatypes.generated.Uint256(_value)), \n                Collections.<TypeReference<?>>emptyList());\n        return executeRemoteCallTransaction(function);\n    }\n\n    public RemoteCall<BigInteger> totalSupply() {\n        final Function function = new Function(FUNC_TOTALSUPPLY, \n                Arrays.<Type>asList(), \n                Arrays.<TypeReference<?>>asList(new TypeReference<Uint256>() {}));\n        return executeRemoteCallSingleValueReturn(function, BigInteger.class);\n    }\n\n    public RemoteCall<TransactionReceipt> transferFrom(String _from, String _to, BigInteger _value) {\n        final Function function = new Function(\n                FUNC_TRANSFERFROM, \n                Arrays.<Type>asList(new org.web3j.abi.datatypes.Address(_from), \n                new org.web3j.abi.datatypes.Address(_to), \n                new org.web3j.abi.datatypes.generated.Uint256(_value)), \n                Collections.<TypeReference<?>>emptyList());\n        return executeRemoteCallTransaction(function);\n    }\n\n    public RemoteCall<BigInteger> decimals() {\n        final Function function = new Function(FUNC_DECIMALS, \n                Arrays.<Type>asList(), \n                Arrays.<TypeReference<?>>asList(new TypeReference<Uint8>() {}));\n        return executeRemoteCallSingleValueReturn(function, BigInteger.class);\n    }\n\n    public RemoteCall<String> version() {\n        final Function function = new Function(FUNC_VERSION, \n                Arrays.<Type>asList(), \n                Arrays.<TypeReference<?>>asList(new TypeReference<Utf8String>() {}));\n        return executeRemoteCallSingleValueReturn(function, String.class);\n    }\n\n    public RemoteCall<BigInteger> balanceOf(String _owner) {\n        final Function function = new Function(FUNC_BALANCEOF, \n                Arrays.<Type>asList(new org.web3j.abi.datatypes.Address(_owner)), \n                Arrays.<TypeReference<?>>asList(new TypeReference<Uint256>() {}));\n        return executeRemoteCallSingleValueReturn(function, BigInteger.class);\n    }\n\n    public RemoteCall<String> symbol() {\n        final Function function = new Function(FUNC_SYMBOL, \n                Arrays.<Type>asList(), \n                Arrays.<TypeReference<?>>asList(new TypeReference<Utf8String>() {}));\n        return executeRemoteCallSingleValueReturn(function, String.class);\n    }\n\n    public RemoteCall<TransactionReceipt> transfer(String _to, BigInteger _value) {\n        final Function function = new Function(\n                FUNC_TRANSFER, \n                Arrays.<Type>asList(new org.web3j.abi.datatypes.Address(_to), \n                new org.web3j.abi.datatypes.generated.Uint256(_value)), \n                Collections.<TypeReference<?>>emptyList());\n        return executeRemoteCallTransaction(function);\n    }\n\n    public RemoteCall<TransactionReceipt> approveAndCall(String _spender, BigInteger _value, byte[] _extraData) {\n        final Function function = new Function(\n                FUNC_APPROVEANDCALL, \n                Arrays.<Type>asList(new org.web3j.abi.datatypes.Address(_spender), \n                new org.web3j.abi.datatypes.generated.Uint256(_value), \n                new org.web3j.abi.datatypes.DynamicBytes(_extraData)), \n                Collections.<TypeReference<?>>emptyList());\n        return executeRemoteCallTransaction(function);\n    }\n\n    public RemoteCall<BigInteger> allowance(String _owner, String _spender) {\n        final Function function = new Function(FUNC_ALLOWANCE, \n                Arrays.<Type>asList(new org.web3j.abi.datatypes.Address(_owner), \n                new org.web3j.abi.datatypes.Address(_spender)), \n                Arrays.<TypeReference<?>>asList(new TypeReference<Uint256>() {}));\n        return executeRemoteCallSingleValueReturn(function, BigInteger.class);\n    }\n\n    public List<TransferEventResponse> getTransferEvents(TransactionReceipt transactionReceipt) {\n        List<Contract.EventValuesWithLog> valueList = extractEventParametersWithLog(TRANSFER_EVENT, transactionReceipt);\n        ArrayList<TransferEventResponse> responses = new ArrayList<TransferEventResponse>(valueList.size());\n        for (Contract.EventValuesWithLog eventValues : valueList) {\n            TransferEventResponse typedResponse = new TransferEventResponse();\n            typedResponse.log = eventValues.getLog();\n            typedResponse._from = (String) eventValues.getIndexedValues().get(0).getValue();\n            typedResponse._to = (String) eventValues.getIndexedValues().get(1).getValue();\n            typedResponse._value = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue();\n            responses.add(typedResponse);\n        }\n        return responses;\n    }\n\n    public Flowable<TransferEventResponse> transferEventFlowable(EthFilter filter) {\n        return web3j.ethLogFlowable(filter).map(new io.reactivex.functions.Function<Log, TransferEventResponse>() {\n            @Override\n            public TransferEventResponse apply(Log log) {\n                Contract.EventValuesWithLog eventValues = extractEventParametersWithLog(TRANSFER_EVENT, log);\n                TransferEventResponse typedResponse = new TransferEventResponse();\n                typedResponse.log = log;\n                typedResponse._from = (String) eventValues.getIndexedValues().get(0).getValue();\n                typedResponse._to = (String) eventValues.getIndexedValues().get(1).getValue();\n                typedResponse._value = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue();\n                return typedResponse;\n            }\n        });\n    }\n\n    public Flowable<TransferEventResponse> transferEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) {\n        EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress());\n        filter.addSingleTopic(EventEncoder.encode(TRANSFER_EVENT));\n        return transferEventFlowable(filter);\n    }\n\n    public List<ApprovalEventResponse> getApprovalEvents(TransactionReceipt transactionReceipt) {\n        List<Contract.EventValuesWithLog> valueList = extractEventParametersWithLog(APPROVAL_EVENT, transactionReceipt);\n        ArrayList<ApprovalEventResponse> responses = new ArrayList<ApprovalEventResponse>(valueList.size());\n        for (Contract.EventValuesWithLog eventValues : valueList) {\n            ApprovalEventResponse typedResponse = new ApprovalEventResponse();\n            typedResponse.log = eventValues.getLog();\n            typedResponse._owner = (String) eventValues.getIndexedValues().get(0).getValue();\n            typedResponse._spender = (String) eventValues.getIndexedValues().get(1).getValue();\n            typedResponse._value = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue();\n            responses.add(typedResponse);\n        }\n        return responses;\n    }\n\n    public Flowable<ApprovalEventResponse> approvalEventFlowable(EthFilter filter) {\n        return web3j.ethLogFlowable(filter).map(new io.reactivex.functions.Function<Log, ApprovalEventResponse>() {\n            @Override\n            public ApprovalEventResponse apply(Log log) {\n                Contract.EventValuesWithLog eventValues = extractEventParametersWithLog(APPROVAL_EVENT, log);\n                ApprovalEventResponse typedResponse = new ApprovalEventResponse();\n                typedResponse.log = log;\n                typedResponse._owner = (String) eventValues.getIndexedValues().get(0).getValue();\n                typedResponse._spender = (String) eventValues.getIndexedValues().get(1).getValue();\n                typedResponse._value = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue();\n                return typedResponse;\n            }\n        });\n    }\n\n    public Flowable<ApprovalEventResponse> approvalEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) {\n        EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress());\n        filter.addSingleTopic(EventEncoder.encode(APPROVAL_EVENT));\n        return approvalEventFlowable(filter);\n    }\n\n    @Deprecated\n    public static HumanStandardToken load(String contractAddress, Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) {\n        return new HumanStandardToken(contractAddress, web3j, credentials, gasPrice, gasLimit);\n    }\n\n    @Deprecated\n    public static HumanStandardToken load(String contractAddress, Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) {\n        return new HumanStandardToken(contractAddress, web3j, transactionManager, gasPrice, gasLimit);\n    }\n\n    public static HumanStandardToken load(String contractAddress, Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) {\n        return new HumanStandardToken(contractAddress, web3j, credentials, contractGasProvider);\n    }\n\n    public static HumanStandardToken load(String contractAddress, Web3j web3j, TransactionManager transactionManager, ContractGasProvider contractGasProvider) {\n        return new HumanStandardToken(contractAddress, web3j, transactionManager, contractGasProvider);\n    }\n\n    public static RemoteCall<HumanStandardToken> deploy(Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider, BigInteger _initialAmount, String _tokenName, BigInteger _decimalUnits, String _tokenSymbol) {\n        String encodedConstructor = FunctionEncoder.encodeConstructor(Arrays.<Type>asList(new org.web3j.abi.datatypes.generated.Uint256(_initialAmount), \n                new org.web3j.abi.datatypes.Utf8String(_tokenName), \n                new org.web3j.abi.datatypes.generated.Uint8(_decimalUnits), \n                new org.web3j.abi.datatypes.Utf8String(_tokenSymbol)));\n        return deployRemoteCall(HumanStandardToken.class, web3j, credentials, contractGasProvider, BINARY, encodedConstructor);\n    }\n\n    public static RemoteCall<HumanStandardToken> deploy(Web3j web3j, TransactionManager transactionManager, ContractGasProvider contractGasProvider, BigInteger _initialAmount, String _tokenName, BigInteger _decimalUnits, String _tokenSymbol) {\n        String encodedConstructor = FunctionEncoder.encodeConstructor(Arrays.<Type>asList(new org.web3j.abi.datatypes.generated.Uint256(_initialAmount), \n                new org.web3j.abi.datatypes.Utf8String(_tokenName), \n                new org.web3j.abi.datatypes.generated.Uint8(_decimalUnits), \n                new org.web3j.abi.datatypes.Utf8String(_tokenSymbol)));\n        return deployRemoteCall(HumanStandardToken.class, web3j, transactionManager, contractGasProvider, BINARY, encodedConstructor);\n    }\n\n    @Deprecated\n    public static RemoteCall<HumanStandardToken> deploy(Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit, BigInteger _initialAmount, String _tokenName, BigInteger _decimalUnits, String _tokenSymbol) {\n        String encodedConstructor = FunctionEncoder.encodeConstructor(Arrays.<Type>asList(new org.web3j.abi.datatypes.generated.Uint256(_initialAmount), \n                new org.web3j.abi.datatypes.Utf8String(_tokenName), \n                new org.web3j.abi.datatypes.generated.Uint8(_decimalUnits), \n                new org.web3j.abi.datatypes.Utf8String(_tokenSymbol)));\n        return deployRemoteCall(HumanStandardToken.class, web3j, credentials, gasPrice, gasLimit, BINARY, encodedConstructor);\n    }\n\n    @Deprecated\n    public static RemoteCall<HumanStandardToken> deploy(Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit, BigInteger _initialAmount, String _tokenName, BigInteger _decimalUnits, String _tokenSymbol) {\n        String encodedConstructor = FunctionEncoder.encodeConstructor(Arrays.<Type>asList(new org.web3j.abi.datatypes.generated.Uint256(_initialAmount), \n                new org.web3j.abi.datatypes.Utf8String(_tokenName), \n                new org.web3j.abi.datatypes.generated.Uint8(_decimalUnits), \n                new org.web3j.abi.datatypes.Utf8String(_tokenSymbol)));\n        return deployRemoteCall(HumanStandardToken.class, web3j, transactionManager, gasPrice, gasLimit, BINARY, encodedConstructor);\n    }\n\n    public static class TransferEventResponse {\n        public Log log;\n\n        public String _from;\n\n        public String _to;\n\n        public BigInteger _value;\n    }\n\n    public static class ApprovalEventResponse {\n        public Log log;\n\n        public String _owner;\n\n        public String _spender;\n\n        public BigInteger _value;\n    }\n}\n"
  },
  {
    "path": "src/main/resources/config/application.yml",
    "content": "# Port to run on\nserver:\n  port: ${port:8081}\n\n# Our log file path and name\nlogging:\n  file: logs/erc20-rest-service.log\n\n# Endpoint of an Ethereum or Quorum node we wish to use.\n# To use IPC simply provide a file path to the socket, such as /path/to/geth.ipc\nnodeEndpoint: http://localhost:22000\n\n# The Ethereum or Quorum address we wish to use when transacting.\n# Note - this address must be already unlocked in the client\nfromAddress: \"0xed9d02e382b34818e88b88a309c7fe71e65f419d\"\n"
  },
  {
    "path": "src/main/resources/logback.xml",
    "content": "<!--<?xml version=\"1.0\" encoding=\"UTF-8\"?>-->\n<!--<configuration>-->\n<!--    &lt;!&ndash; Prevent Spring trying to log to /tmp/spring.log on Linux hosts. This needs to be before-->\n<!--    the defaults include &ndash;&gt;-->\n<!--    <property name=\"LOG_TEMP\" value=\"./logs\" />-->\n<!--    <include resource=\"org/springframework/boot/logging/logback/defaults.xml\"/>-->\n<!--    <property name=\"LOG_FILE\" value=\"${LOG_FILE:-${LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}/}spring.log}\"/>-->\n<!--    &lt;!&ndash; Uncomment here and below to allow console logging too &ndash;&gt;-->\n<!--    &lt;!&ndash;<include resource=\"org/springframework/boot/logging/logback/console-appender.xml\"/>&ndash;&gt;-->\n\n<!--    <appender name=\"ROLLING-FILE\"-->\n<!--              class=\"ch.qos.logback.core.rolling.RollingFileAppender\">-->\n<!--        <encoder>-->\n<!--            <pattern>${FILE_LOG_PATTERN}</pattern>-->\n<!--        </encoder>-->\n<!--        <file>${LOG_FILE}</file>-->\n<!--        <rollingPolicy class=\"ch.qos.logback.core.rolling.TimeBasedRollingPolicy\">-->\n<!--            &lt;!&ndash; daily rollover &ndash;&gt;-->\n<!--            <fileNamePattern>${LOG_FILE}.%d{yyyy-MM-dd}.log</fileNamePattern>-->\n<!--        </rollingPolicy>-->\n<!--    </appender>-->\n\n<!--    <root level=\"INFO\">-->\n<!--        &lt;!&ndash;<appender-ref ref=\"CONSOLE\"/>&ndash;&gt;-->\n<!--        <appender-ref ref=\"ROLLING-FILE\"/>-->\n<!--    </root>-->\n<!--</configuration>-->\n<configuration>\n\n    <appender name=\"STDOUT\" class=\"ch.qos.logback.core.ConsoleAppender\">\n        <!-- encoders are assigned the type\n             ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->\n        <encoder>\n            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>\n        </encoder>\n    </appender>\n\n    <root level=\"INFO\">\n        <appender-ref ref=\"STDOUT\" />\n    </root>\n</configuration>"
  },
  {
    "path": "src/main/resources/solidity/contract/HumanStandardToken.sol",
    "content": "/*\nThis Token Contract implements the standard token functionality (https://github.com/ethereum/EIPs/issues/20) as well as the following OPTIONAL extras intended for use by humans.\n\nIn other words. This is intended for deployment in something like a Token Factory or Mist wallet, and then used by humans.\nImagine coins, currencies, shares, voting weight, etc.\nMachine-based, rapid creation of many tokens would not necessarily need these extra features or will be minted in other manners.\n\n1) Initial Finite Supply (upon creation one specifies how much is minted).\n2) In the absence of a token registry: Optional Decimal, Symbol & Name.\n3) Optional approveAndCall() functionality to notify a contract if an approval() has occurred.\n\n.*/\n\nimport \"./StandardToken.sol\";\n\npragma solidity ^0.5.2;\n\ncontract HumanStandardToken is StandardToken {\n\n    function () external {\n        //if ether is sent to this address, send it back.\n        revert();\n    }\n\n    /* Public variables of the token */\n\n    /*\n    NOTE:\n    The following variables are OPTIONAL vanities. One does not have to include them.\n    They allow one to customise the token contract & in no way influences the core functionality.\n    Some wallets/interfaces might not even bother to look at this information.\n    */\n    string public name;                   //fancy name: eg Simon Bucks\n    uint8 public decimals;                //How many decimals to show. ie. There could 1000 base units with 3 decimals. Meaning 0.980 SBX = 980 base units. It's like comparing 1 wei to 1 ether.\n    string public symbol;                 //An identifier: eg SBX\n    string public version = 'H0.1';       //human 0.1 standard. Just an arbitrary versioning scheme.\n\n    constructor(\n        uint256 _initialAmount,\n        string memory _tokenName,\n        uint8 _decimalUnits,\n        string memory _tokenSymbol\n        ) public {\n        balances[msg.sender] = _initialAmount;               // Give the creator all initial tokens\n        totalSupply = _initialAmount;                        // Update total supply\n        name = _tokenName;                                   // Set the name for display purposes\n        decimals = _decimalUnits;                            // Amount of decimals for display purposes\n        symbol = _tokenSymbol;                               // Set the symbol for display purposes\n    }\n\n    /* Approves and then calls the receiving contract */\n    function approveAndCall(address _spender, uint256 _value, bytes calldata _extraData) external returns (bool success) {\n        allowed[msg.sender][_spender] = _value;\n        emit Approval(msg.sender, _spender, _value);\n\n        //call the receiveApproval function on the contract you want to be notified. This crafts the function signature manually so one doesn't have to include a contract in here just for this.\n        //receiveApproval(address _from, uint256 _value, address _tokenContract, bytes _extraData)\n        //it is assumed that when does this that the call *should* succeed, otherwise one would use vanilla approve instead.\n        (bool success, ) = _spender.call(abi.encode(\"receiveApproval(address,uint256,address,bytes)\"));\n\n        if(!success) { revert(); }\n        return true;\n    }\n}\n"
  },
  {
    "path": "src/main/resources/solidity/contract/HumanStandardTokenFactory.sol",
    "content": "import \"./HumanStandardToken.sol\";\n\npragma solidity ^0.5.2;\n\ncontract HumanStandardTokenFactory {\n\n    mapping(address => address[]) public created;\n    mapping(address => bool) public isHumanToken; //verify without having to do a bytecode check.\n    bytes public humanStandardByteCode;\n\n    function HumanStandardTokenFactory() {\n      //upon creation of the factory, deploy a HumanStandardToken (parameters are meaningless) and store the bytecode provably.\n      address verifiedToken = createHumanStandardToken(10000, \"Verify Token\", 3, \"VTX\");\n      humanStandardByteCode = codeAt(verifiedToken);\n    }\n\n    //verifies if a contract that has been deployed is a Human Standard Token.\n    //NOTE: This is a very expensive function, and should only be used in an eth_call. ~800k gas\n    function verifyHumanStandardToken(address _tokenContract) returns (bool) {\n      bytes memory fetchedTokenByteCode = codeAt(_tokenContract);\n\n      if (fetchedTokenByteCode.length != humanStandardByteCode.length) {\n        return false; //clear mismatch\n      }\n\n      //starting iterating through it if lengths match\n      for (uint i = 0; i < fetchedTokenByteCode.length; i ++) {\n        if (fetchedTokenByteCode[i] != humanStandardByteCode[i]) {\n          return false;\n        }\n      }\n\n      return true;\n    }\n\n    //for now, keeping this internal. Ideally there should also be a live version of this that any contract can use, lib-style.\n    //retrieves the bytecode at a specific address.\n    function codeAt(address _addr) internal returns (bytes o_code) {\n      assembly {\n          // retrieve the size of the code, this needs assembly\n          let size := extcodesize(_addr)\n          // allocate output byte array - this could also be done without assembly\n          // by using o_code = new bytes(size)\n          o_code := mload(0x40)\n          // new \"memory end\" including padding\n          mstore(0x40, add(o_code, and(add(add(size, 0x20), 0x1f), not(0x1f))))\n          // store length in memory\n          mstore(o_code, size)\n          // actually retrieve the code, this needs assembly\n          extcodecopy(_addr, add(o_code, 0x20), 0, size)\n      }\n    }\n\n    function createHumanStandardToken(uint256 _initialAmount, string _name, uint8 _decimals, string _symbol) returns (address) {\n\n        HumanStandardToken newToken = (new HumanStandardToken(_initialAmount, _name, _decimals, _symbol));\n        created[msg.sender].push(address(newToken));\n        isHumanToken[address(newToken)] = true;\n        newToken.transfer(msg.sender, _initialAmount); //the factory will own the created tokens. You must transfer them.\n        return address(newToken);\n    }\n}\n"
  },
  {
    "path": "src/main/resources/solidity/contract/StandardToken.sol",
    "content": "/*\nYou should inherit from StandardToken or, for a token like you would want to\ndeploy in something like Mist, see HumanStandardToken.sol.\n(This implements ONLY the standard functions and NOTHING else.\nIf you deploy this, you won't have anything useful.)\n\nImplements ERC 20 Token standard: https://github.com/ethereum/EIPs/issues/20\n.*/\npragma solidity ^0.5.2;\n\nimport \"./Token.sol\";\n\ncontract StandardToken is Token {\n\n    function transfer(address _to, uint256 _value) public returns (bool success) {\n        //Default assumes totalSupply can't be over max (2^256 - 1).\n        //If your token leaves out totalSupply and can issue more tokens as time goes on, you need to check if it doesn't wrap.\n        //Replace the if with this one instead.\n        //if (balances[msg.sender] >= _value && balances[_to] + _value > balances[_to]) {\n        if (balances[msg.sender] >= _value && _value > 0) {\n            balances[msg.sender] -= _value;\n            balances[_to] += _value;\n            emit Transfer(msg.sender, _to, _value);\n            return true;\n        } else { return false; }\n    }\n\n    function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {\n        //same as above. Replace this line with the following if you want to protect against wrapping uints.\n        //if (balances[_from] >= _value && allowed[_from][msg.sender] >= _value && balances[_to] + _value > balances[_to]) {\n        if (balances[_from] >= _value && allowed[_from][msg.sender] >= _value && _value > 0) {\n            balances[_to] += _value;\n            balances[_from] -= _value;\n            allowed[_from][msg.sender] -= _value;\n            emit Transfer(_from, _to, _value);\n            return true;\n        } else { return false; }\n    }\n\n    function balanceOf(address _owner) public view returns (uint256 balance) {\n        return balances[_owner];\n    }\n\n    function approve(address _spender, uint256 _value) public returns (bool success) {\n        allowed[msg.sender][_spender] = _value;\n        emit Approval(msg.sender, _spender, _value);\n        return true;\n    }\n\n    function allowance(address _owner, address _spender) public view returns (uint256 remaining) {\n      return allowed[_owner][_spender];\n    }\n\n    mapping (address => uint256) balances;\n    mapping (address => mapping (address => uint256)) allowed;\n}\n"
  },
  {
    "path": "src/main/resources/solidity/contract/Token.sol",
    "content": "// Abstract contract for the full ERC 20 Token standard\n// https://github.com/ethereum/EIPs/issues/20\npragma solidity ^0.5.2;\n\ncontract Token {\n    /* This is a slight change to the ERC20 base standard.\n    function totalSupply() constant returns (uint256 supply);\n    is replaced with:\n    uint256 public totalSupply;\n    This automatically creates a getter function for the totalSupply.\n    This is moved to the base contract since public getter functions are not\n    currently recognised as an implementation of the matching abstract\n    function by the compiler.\n    */\n    /// total amount of tokens\n    uint256 public totalSupply;\n\n    /// @param _owner The address from which the balance will be retrieved\n    /// @return The balance\n    function balanceOf(address _owner) public view returns (uint256 balance);\n\n    /// @notice send `_value` token to `_to` from `msg.sender`\n    /// @param _to The address of the recipient\n    /// @param _value The amount of token to be transferred\n    /// @return Whether the transfer was successful or not\n    function transfer(address _to, uint256 _value) public returns (bool success);\n\n    /// @notice send `_value` token to `_to` from `_from` on the condition it is approved by `_from`\n    /// @param _from The address of the sender\n    /// @param _to The address of the recipient\n    /// @param _value The amount of token to be transferred\n    /// @return Whether the transfer was successful or not\n    function transferFrom(address _from, address _to, uint256 _value) public returns (bool success);\n\n    /// @notice `msg.sender` approves `_spender` to spend `_value` tokens\n    /// @param _spender The address of the account able to transfer the tokens\n    /// @param _value The amount of tokens to be approved for transfer\n    /// @return Whether the approval was successful or not\n    function approve(address _spender, uint256 _value) public returns (bool success);\n\n    /// @param _owner The address of the account owning tokens\n    /// @param _spender The address of the account able to transfer the tokens\n    /// @return Amount of remaining tokens allowed to spent\n    function allowance(address _owner, address _spender) public view returns (uint256 remaining);\n\n    event Transfer(address indexed _from, address indexed _to, uint256 _value);\n    event Approval(address indexed _owner, address indexed _spender, uint256 _value);\n}\n"
  },
  {
    "path": "src/main/resources/solidity/contract/build/HumanStandardToken.abi",
    "content": "[{\"constant\":true,\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_spender\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_from\",\"type\":\"address\"},{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"name\":\"\",\"type\":\"uint8\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"name\":\"balance\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_spender\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"},{\"name\":\"_extraData\",\"type\":\"bytes\"}],\"name\":\"approveAndCall\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\"},{\"name\":\"_spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"name\":\"remaining\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"name\":\"_initialAmount\",\"type\":\"uint256\"},{\"name\":\"_tokenName\",\"type\":\"string\"},{\"name\":\"_decimalUnits\",\"type\":\"uint8\"},{\"name\":\"_tokenSymbol\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"fallback\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"_from\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_to\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"_owner\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_spender\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"}]"
  },
  {
    "path": "src/main/resources/solidity/contract/build/StandardToken.abi",
    "content": "[{\"constant\":false,\"inputs\":[{\"name\":\"_spender\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_from\",\"type\":\"address\"},{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"name\":\"balance\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\"},{\"name\":\"_spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"name\":\"remaining\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"_from\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_to\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"_owner\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_spender\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"}]"
  },
  {
    "path": "src/main/resources/solidity/contract/build/Token.abi",
    "content": "[{\"constant\":false,\"inputs\":[{\"name\":\"_spender\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_from\",\"type\":\"address\"},{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"name\":\"balance\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\"},{\"name\":\"_spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"name\":\"remaining\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"_from\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_to\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"_owner\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_spender\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"}]"
  },
  {
    "path": "src/test/java/io/blk/erc20/ControllerIT.java",
    "content": "package io.blk.erc20;\n\nimport java.math.BigInteger;\nimport java.util.Arrays;\n\nimport org.junit.Ignore;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.boot.test.web.client.TestRestTemplate;\nimport org.springframework.http.HttpEntity;\nimport org.springframework.http.HttpHeaders;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.MediaType;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\n\nimport static junit.framework.TestCase.assertNull;\nimport static org.hamcrest.CoreMatchers.is;\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertNotNull;\nimport static org.junit.Assert.assertThat;\nimport static org.junit.Assert.assertTrue;\n\n@RunWith(SpringJUnit4ClassRunner.class)\n@SpringBootTest(webEnvironment= SpringBootTest.WebEnvironment.RANDOM_PORT)\npublic class ControllerIT {\n\n    // key2\n    private static final String OTHER_ACCOUNT = \"ca843569e3427144cead5e4d5999a3d0ccf92b8e\";\n    // Transaction manager 2\n    private static final String PRIVATE_FOR = \"QfeDAys9MPDs2XHExtc84jKGHxZg/aj52DTh0vtA3Xc=\";\n\n    @Autowired\n    private NodeConfiguration nodeConfiguration;\n\n    @Autowired\n    private TestRestTemplate restTemplate;\n\n\n\n    @Test\n    public void testConfig() {\n        ResponseEntity<NodeConfiguration> responseEntity =\n                this.restTemplate.getForEntity(\"/config\", NodeConfiguration.class);\n        verifyHttpStatus(responseEntity);\n        assertNotNull(responseEntity.getBody());\n    }\n\n    @Ignore\n    @Test\n    public void testLifeCycle() {\n        Controller.ContractSpecification contractSpecification =\n                new Controller.ContractSpecification(\n                        BigInteger.valueOf(1000000), \"Quorum Token\", BigInteger.valueOf(25), \"QT\");\n\n        String contractAddress = deploy(contractSpecification);\n\n        verifyName(contractAddress, contractSpecification.getTokenName());\n        verifySymbol(contractAddress, contractSpecification.getTokenSymbol());\n        verifyDecimals(contractAddress, contractSpecification.getDecimalUnits());\n        verifyVersion(contractAddress, \"H0.1\");\n\n        verifyTotalSupply(contractAddress, contractSpecification.getInitialAmount());\n        verifyBalanceOf(contractAddress,\n                nodeConfiguration.getFromAddress(), contractSpecification.getInitialAmount());\n\n        Controller.ApproveRequest approveRequest = new Controller.ApproveRequest(\n                OTHER_ACCOUNT, BigInteger.valueOf(10000));\n        verifyApproveTx(contractAddress, approveRequest);\n\n        verifyAllowance(\n                contractAddress, nodeConfiguration.getFromAddress(), OTHER_ACCOUNT,\n                approveRequest.getValue());\n\n        Controller.TransferRequest transferRequest = new Controller.TransferRequest(\n                OTHER_ACCOUNT, BigInteger.valueOf(10000));\n        verifyTransferTx(contractAddress, transferRequest);\n        verifyBalanceOf(\n                contractAddress,\n                transferRequest.getTo(),\n                transferRequest.getValue());\n        verifyBalanceOf(\n                contractAddress,\n                nodeConfiguration.getFromAddress(),\n                contractSpecification.getInitialAmount().subtract(transferRequest.getValue()));\n\n        // Needs to be performed by another account, hence this will fail\n        Controller.TransferFromRequest transferFromRequest =\n                new Controller.TransferFromRequest(\n                        nodeConfiguration.getFromAddress(), OTHER_ACCOUNT, BigInteger.valueOf(1000));\n        verifyTransferFromTxFailure(contractAddress, transferFromRequest);\n        // Therefore our balance remains the same\n        verifyBalanceOf(\n                contractAddress,\n                transferFromRequest.getFrom(),\n                contractSpecification.getInitialAmount().subtract(transferRequest.getValue()));\n    }\n\n    private String deploy(\n            Controller.ContractSpecification contractSpecification) {\n\n        ResponseEntity<String> responseEntity =\n                this.restTemplate.postForEntity(\n                        \"/deploy\", buildEntity(contractSpecification), String.class);\n        verifyHttpStatus(responseEntity);\n\n        String contractAddress = responseEntity.getBody();\n        assertFalse(contractAddress.isEmpty());\n        return contractAddress;\n    }\n\n    private void verifyName(String contractAddress, String name) {\n        ResponseEntity<String> responseEntity =\n                this.restTemplate.getForEntity(\n                        \"/\" + contractAddress + \"\" + \"/name\", String.class);\n        verifyHttpStatus(responseEntity);\n        assertThat(responseEntity.getBody(), is(name));\n    }\n\n    private void verifyTotalSupply(String contractAddress, BigInteger totalSupply) {\n        ResponseEntity<BigInteger> responseEntity =\n                this.restTemplate.getForEntity(\n                        \"/\" + contractAddress + \"\" + \"/totalSupply\", BigInteger.class);\n        verifyHttpStatus(responseEntity);\n        assertThat(responseEntity.getBody(), is(totalSupply));\n    }\n\n    private void verifyDecimals(String contractAddress, BigInteger decimals) {\n        ResponseEntity<BigInteger> responseEntity =\n                this.restTemplate.getForEntity(\n                        \"/\" + contractAddress + \"\" + \"/decimals\", BigInteger.class);\n        verifyHttpStatus(responseEntity);\n        assertThat(responseEntity.getBody(), is(decimals));\n    }\n\n    private void verifyVersion(String contractAddress, String version) {\n        ResponseEntity<String> responseEntity =\n                this.restTemplate.getForEntity(\n                        \"/\" + contractAddress + \"\" + \"/version\", String.class);\n        verifyHttpStatus(responseEntity);\n        assertThat(responseEntity.getBody(), is(version));\n    }\n\n    private void verifyBalanceOf(String contractAddress, String ownerAddress, BigInteger balance) {\n        ResponseEntity<BigInteger> responseEntity =\n                this.restTemplate.getForEntity(\n                        \"/\" + contractAddress + \"\" + \"/balanceOf/\" + ownerAddress,\n                        BigInteger.class);\n        verifyHttpStatus(responseEntity);\n        assertThat(responseEntity.getBody(), is(balance));\n    }\n\n    private void verifySymbol(String contractAddress, String symbol) {\n        ResponseEntity<String> responseEntity =\n                this.restTemplate.getForEntity(\n                        \"/\" + contractAddress + \"\" + \"/symbol\", String.class);\n        verifyHttpStatus(responseEntity);\n        assertThat(responseEntity.getBody(), is(symbol));\n    }\n\n    private void verifyAllowance(\n            String contractAddress,\n            String ownerAddress,\n            String spenderAddress,\n            BigInteger expected) {\n        ResponseEntity<BigInteger> responseEntity =\n                this.restTemplate.getForEntity(\n                        \"/\" + contractAddress\n                                + \"/allowance?\"\n                                + \"ownerAddress={ownerAddress}\"\n                                + \"&spenderAddress={spenderAddress}\",\n                        BigInteger.class,\n                        ownerAddress,\n                        spenderAddress);\n        verifyHttpStatus(responseEntity);\n        assertThat(responseEntity.getBody(), is(expected));\n    }\n\n    private void verifyTransferFromTxFailure(\n            String contractAddress, Controller.TransferFromRequest transferFromRequest) {\n        ResponseEntity<TransactionResponse> responseEntity =\n                this.restTemplate.postForEntity(\n                        \"/\" + contractAddress + \"/transferFrom\",\n                        buildEntity(transferFromRequest),\n                        TransactionResponse.class);\n        verifyPostResponseFailure(responseEntity);\n    }\n\n    private void verifyApproveTx(\n            String contractAddress, Controller.ApproveRequest approveRequest) {\n        ResponseEntity<TransactionResponse> responseEntity =\n                this.restTemplate.postForEntity(\n                        \"/\" + contractAddress + \"/approve\",\n                        buildEntity(approveRequest),\n                        TransactionResponse.class);\n        verifyPostResponse(responseEntity);\n    }\n\n    private void verifyTransferTx(\n            String contractAddress, Controller.TransferRequest transferRequest) {\n        ResponseEntity<TransactionResponse> responseEntity =\n                this.restTemplate.postForEntity(\n                        \"/\" + contractAddress + \"/transfer\",\n                        buildEntity(transferRequest),\n                        TransactionResponse.class);\n        verifyPostResponse(responseEntity);\n    }\n\n    private <T> HttpEntity<T> buildEntity(T body) {\n        HttpHeaders headers = new HttpHeaders();\n        headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));\n        headers.setContentType(MediaType.APPLICATION_JSON);\n        headers.add(\"privateFor\", PRIVATE_FOR);\n\n        return new HttpEntity<>(body, headers);\n    }\n\n    private <T> void verifyHttpStatus(ResponseEntity<T> responseEntity) {\n        assertThat(responseEntity.getStatusCode(), is(HttpStatus.OK));\n    }\n\n    private void verifyPostResponse(ResponseEntity<TransactionResponse> responseEntity) {\n        verifyPostResponseBody(responseEntity);\n        assertNotNull(responseEntity.getBody().getEvent());\n    }\n\n    private void verifyPostResponseFailure(ResponseEntity<TransactionResponse> responseEntity) {\n        assertNull(responseEntity.getBody().getEvent());\n    }\n\n    private void verifyPostResponseBody(ResponseEntity<TransactionResponse> responseEntity) {\n        verifyHttpStatus(responseEntity);\n        TransactionResponse body = responseEntity.getBody();\n        assertNotNull(body);\n        String transactionHash = body.getTransactionHash();\n        assertTrue(transactionHash.startsWith(\"0x\"));\n        assertThat(transactionHash.length(), is(66));\n    }\n}\n"
  },
  {
    "path": "src/test/resources/logback-test.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<configuration>\n    <!-- Prevent Spring trying to log to /tmp/spring.log on Linux hosts. This needs to be before\n    the defaults include -->\n    <property name=\"LOG_TEMP\" value=\"./logs\" />\n    <include resource=\"org/springframework/boot/logging/logback/base.xml\" />\n    <logger name=\"org.web3j\" level=\"debug\" />\n    <logger name=\"org.apache.http.wire\" level=\"debug\" />\n    <root level=\"INFO\" />\n</configuration>"
  }
]