├── .classpath ├── .gitattributes ├── .gitignore ├── .project ├── .settings ├── org.eclipse.buildship.core.prefs └── org.eclipse.jdt.core.prefs ├── LICENSE ├── README.md ├── bin └── .gitignore ├── build.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── src ├── main ├── java │ └── com │ │ └── scaleton │ │ └── dfinity │ │ ├── agent │ │ ├── Agent.java │ │ ├── AgentBuilder.java │ │ ├── AgentConfig.java │ │ ├── AgentError.java │ │ ├── ByteUtils.java │ │ ├── MethodType.java │ │ ├── NonceFactory.java │ │ ├── ProxyBuilder.java │ │ ├── QueryBuilder.java │ │ ├── ReplicaTransport.java │ │ ├── RequestStatusResponse.java │ │ ├── ResponseAuthentication.java │ │ ├── Serialize.java │ │ ├── Serializer.java │ │ ├── Status.java │ │ ├── UpdateBuilder.java │ │ ├── Value.java │ │ ├── Waiter.java │ │ ├── annotations │ │ │ ├── Agent.java │ │ │ ├── Canister.java │ │ │ ├── EffectiveCanister.java │ │ │ ├── Identity.java │ │ │ ├── IdentityType.java │ │ │ ├── Transport.java │ │ │ ├── TransportType.java │ │ │ └── Waiter.java │ │ ├── hashtree │ │ │ ├── EmptyHashTreeNode.java │ │ │ ├── ForkHashTreeNode.java │ │ │ ├── HashTree.java │ │ │ ├── HashTreeDeserializer.java │ │ │ ├── HashTreeNode.java │ │ │ ├── Label.java │ │ │ ├── LabeledHashTreeNode.java │ │ │ ├── LeafHashTreeNode.java │ │ │ ├── LookupResult.java │ │ │ ├── NodeType.java │ │ │ └── PrunedHashTreeNode.java │ │ ├── http │ │ │ ├── ReplicaApacheHttpTransport.java │ │ │ ├── ReplicaHttpProperties.java │ │ │ └── ReplicaOkHttpTransport.java │ │ ├── identity │ │ │ ├── AnonymousIdentity.java │ │ │ ├── BasicIdentity.java │ │ │ ├── Identity.java │ │ │ ├── PemError.java │ │ │ ├── Secp256k1Identity.java │ │ │ └── Signature.java │ │ ├── replicaapi │ │ │ ├── CallReply.java │ │ │ ├── CallRequestContent.java │ │ │ ├── Certificate.java │ │ │ ├── Envelope.java │ │ │ ├── QueryContent.java │ │ │ ├── QueryResponse.java │ │ │ ├── ReadStateContent.java │ │ │ ├── ReadStateResponse.java │ │ │ └── Status.java │ │ └── requestid │ │ │ ├── RequestId.java │ │ │ ├── RequestIdError.java │ │ │ └── RequestIdSerializer.java │ │ ├── candid │ │ ├── Bytes.java │ │ ├── CandidError.java │ │ ├── Deserialize.java │ │ ├── Deserializer.java │ │ ├── IDLBuilder.java │ │ ├── IDLDeserialize.java │ │ ├── IDLUtils.java │ │ ├── Leb128.java │ │ ├── ObjectDeserializer.java │ │ ├── ObjectSerializer.java │ │ ├── Serializer.java │ │ ├── TypeSerialize.java │ │ ├── TypeTable.java │ │ ├── TypeTableResponse.java │ │ ├── ValueSerializer.java │ │ ├── annotations │ │ │ ├── Argument.java │ │ │ ├── Deserializer.java │ │ │ ├── Field.java │ │ │ ├── Ignore.java │ │ │ ├── Name.java │ │ │ ├── QUERY.java │ │ │ ├── Serializer.java │ │ │ └── UPDATE.java │ │ ├── dom │ │ │ ├── DOMDeserializer.java │ │ │ ├── DOMSerDeserBase.java │ │ │ ├── DOMSerializer.java │ │ │ └── DOMUtils.java │ │ ├── jackson │ │ │ ├── JacksonDeserializer.java │ │ │ └── JacksonSerializer.java │ │ ├── jdbc │ │ │ └── JDBCSerializer.java │ │ ├── parser │ │ │ ├── IDLArgs.java │ │ │ ├── IDLField.java │ │ │ ├── IDLType.java │ │ │ └── IDLValue.java │ │ ├── pojo │ │ │ ├── PojoDeserializer.java │ │ │ └── PojoSerializer.java │ │ └── types │ │ │ ├── Label.java │ │ │ ├── Numbers.java │ │ │ ├── Opcode.java │ │ │ └── Type.java │ │ └── types │ │ ├── Principal.java │ │ ├── PrincipalDeserializer.java │ │ ├── PrincipalError.java │ │ └── PrincipalSerializer.java └── resources │ ├── dfinity_agent.properties │ ├── dfinity_candid.properties │ ├── dfinity_pem.properties │ ├── dfinity_requestid.properties │ └── dfinity_types.properties └── test ├── java └── com │ └── scaleton │ └── dfinity │ └── test │ ├── CandidAssert.java │ ├── CandidTest.java │ ├── ComplexArrayPojo.java │ ├── ComplexPojo.java │ ├── DOMTest.java │ ├── HelloProxy.java │ ├── ICTest.java │ ├── IdentityTest.java │ ├── JDBCTest.java │ ├── JacksonPojo.java │ ├── JacksonTest.java │ ├── MockTest.java │ ├── Pojo.java │ ├── PojoTest.java │ ├── PrincipalTest.java │ ├── QueryTest.java │ ├── StatusTest.java │ ├── TestProperties.java │ └── UpdateTest.java ├── main.mo └── resources ├── ComplexNode.xml ├── Ed25519_identity.pem ├── Secp256k1_identity.pem ├── SimpleArrayNode.json ├── SimpleNode.json ├── SimpleNode.xml ├── cbor.echoBool.query.response ├── cbor.echoFloat.query.response ├── cbor.echoInt.query.response ├── cbor.echoOption.query.response ├── cbor.echoPrincipal.query.response ├── cbor.echoRecord.query.response ├── cbor.echoVec.query.response ├── cbor.hello.query.response ├── cbor.peek.query.response ├── cbor.query.response ├── cbor.status.response ├── cbor.update.greet.response ├── rrkah-fqaaa-aaaaa-aaaaq-cai ├── rrkah-fqaaa-aaaaa-aaaaq-cai2.requestStatus ├── simplelogger.properties └── test.properties /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # 2 | # https://help.github.com/articles/dealing-with-line-endings/ 3 | # 4 | # These are explicitly windows files and should use crlf 5 | *.bat text eol=crlf 6 | 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore Gradle project-specific cache directory 2 | .gradle 3 | 4 | # Ignore Gradle build output directory 5 | build 6 | /gradle.properties 7 | /build-export.gradle 8 | /secring.gpg 9 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | dfinityAgent 4 | Project dfinityAgent created by Buildship. 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | org.eclipse.buildship.core.gradleprojectbuilder 15 | 16 | 17 | 18 | 19 | 20 | org.eclipse.jdt.core.javanature 21 | org.eclipse.buildship.core.gradleprojectnature 22 | 23 | 24 | -------------------------------------------------------------------------------- /.settings/org.eclipse.buildship.core.prefs: -------------------------------------------------------------------------------- 1 | arguments= 2 | auto.sync=false 3 | build.scans.enabled=false 4 | connection.gradle.distribution=GRADLE_DISTRIBUTION(VERSION(7.0.2)) 5 | connection.project.dir= 6 | eclipse.preferences.version=1 7 | gradle.user.home= 8 | java.home= 9 | jvm.arguments= 10 | offline.mode=false 11 | override.workspace.settings=true 12 | show.console.view=true 13 | show.executions.view=true 14 | -------------------------------------------------------------------------------- /.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled 3 | org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate 4 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 5 | org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve 6 | org.eclipse.jdt.core.compiler.compliance=1.8 7 | org.eclipse.jdt.core.compiler.debug.lineNumber=generate 8 | org.eclipse.jdt.core.compiler.debug.localVariable=generate 9 | org.eclipse.jdt.core.compiler.debug.sourceFile=generate 10 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error 11 | org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled 12 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error 13 | org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning 14 | org.eclipse.jdt.core.compiler.release=disabled 15 | org.eclipse.jdt.core.compiler.source=1.8 16 | -------------------------------------------------------------------------------- /bin/.gitignore: -------------------------------------------------------------------------------- 1 | /main/ 2 | /test/ 3 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * This file was generated by the Gradle 'init' task. 3 | * 4 | * This generated file contains a sample Java Library project to get you started. 5 | * For more details take a look at the Java Libraries chapter in the Gradle 6 | * User Manual available at https://docs.gradle.org/6.3/userguide/java_library_plugin.html 7 | */ 8 | 9 | plugins { 10 | id 'java' 11 | id 'eclipse' 12 | } 13 | 14 | 15 | group 'com.scaleton.dfinity' 16 | version '0.5.7' 17 | 18 | sourceCompatibility = 1.8 19 | 20 | repositories { 21 | mavenLocal() 22 | mavenCentral() 23 | } 24 | 25 | jar { 26 | manifest { 27 | attributes('Implementation-Title': 'dfinity-agent', 28 | 'Implementation-Version': project.version) 29 | } 30 | 31 | archiveBaseName = 'dfinity-agent' 32 | } 33 | 34 | task fatJar(type: Jar) { 35 | manifest { 36 | attributes('Implementation-Title': 'dfinity-agent', 37 | 'Implementation-Version': project.version) 38 | } 39 | 40 | archiveBaseName = 'dfinity-agent-with-dependencies' 41 | 42 | from { configurations.compileClasspath.collect { it.isDirectory() ? it : zipTree(it) } } 43 | with jar 44 | } 45 | 46 | test { 47 | useJUnitPlatform() 48 | 49 | exclude '**/*ICTest*' 50 | } 51 | 52 | dependencies { 53 | // https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 54 | implementation group: 'org.apache.commons', name: 'commons-lang3', version: '3.12.0' 55 | 56 | // https://mvnrepository.com/artifact/org.apache.httpcomponents.client5/httpclient5 57 | implementation group: 'org.apache.httpcomponents.client5', name: 'httpclient5', version: '5.1' 58 | 59 | // https://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp 60 | implementation group: 'com.squareup.okhttp3', name: 'okhttp', version: '4.9.2' 61 | 62 | // https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind 63 | implementation group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.12.5' 64 | 65 | // https://mvnrepository.com/artifact/com.fasterxml.jackson.datatype/jackson-datatype-jdk8 66 | implementation group: 'com.fasterxml.jackson.datatype', name: 'jackson-datatype-jdk8', version: '2.12.5' 67 | 68 | // https://mvnrepository.com/artifact/com.fasterxml.jackson.dataformat/jackson-dataformat-cbor 69 | implementation group: 'com.fasterxml.jackson.dataformat', name: 'jackson-dataformat-cbor', version: '2.12.5' 70 | 71 | // https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk15on 72 | implementation group: 'org.bouncycastle', name: 'bcprov-jdk15on', version: '1.69' 73 | 74 | // https://mvnrepository.com/artifact/org.bouncycastle/bcpkix-jdk15on 75 | implementation group: 'org.bouncycastle', name: 'bcpkix-jdk15on', version: '1.69' 76 | 77 | // https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-engine 78 | testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: '5.8.0' 79 | 80 | // https://mvnrepository.com/artifact/org.mock-server/mockserver-netty 81 | testImplementation group: 'org.mock-server', name: 'mockserver-netty', version: '5.11.2' 82 | 83 | // https://mvnrepository.com/artifact/org.mock-server/mockserver-junit-rule 84 | testImplementation group: 'org.mock-server', name: 'mockserver-junit-jupiter', version: '5.11.2' 85 | 86 | // https://mvnrepository.com/artifact/org.slf4j/slf4j-simple 87 | testImplementation group: 'org.slf4j', name: 'slf4j-simple', version: '1.7.32' 88 | 89 | // https://mvnrepository.com/artifact/org.skyscreamer/jsonassert 90 | testImplementation group: 'org.skyscreamer', name: 'jsonassert', version: '1.5.0' 91 | 92 | // https://mvnrepository.com/artifact/org.apache.derby/derby 93 | testImplementation group: 'org.apache.derby', name: 'derby', version: '10.14.2.0' 94 | } 95 | 96 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rdobrik/dfinity-agent/ae064f8b9c22c8f3f4d7539ce101fef33862bcf2/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto init 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto init 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :init 68 | @rem Get command-line arguments, handling Windows variants 69 | 70 | if not "%OS%" == "Windows_NT" goto win9xME_args 71 | 72 | :win9xME_args 73 | @rem Slurp the command line arguments. 74 | set CMD_LINE_ARGS= 75 | set _SKIP=2 76 | 77 | :win9xME_args_slurp 78 | if "x%~1" == "x" goto execute 79 | 80 | set CMD_LINE_ARGS=%* 81 | 82 | :execute 83 | @rem Setup the command line 84 | 85 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 86 | 87 | @rem Execute Gradle 88 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 89 | 90 | :end 91 | @rem End local scope for the variables with windows NT shell 92 | if "%ERRORLEVEL%"=="0" goto mainEnd 93 | 94 | :fail 95 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 96 | rem the _cmd.exe /c_ return code! 97 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 98 | exit /b 1 99 | 100 | :mainEnd 101 | if "%OS%"=="Windows_NT" endlocal 102 | 103 | :omega 104 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * This file was generated by the Gradle 'init' task. 3 | * 4 | * The settings file is used to specify which projects to include in your build. 5 | * 6 | * Detailed information about configuring a multi-project build in Gradle can be found 7 | * in the user manual at https://docs.gradle.org/6.3/userguide/multi_project_builds.html 8 | */ 9 | 10 | rootProject.name = 'dfinityAgent' 11 | -------------------------------------------------------------------------------- /src/main/java/com/scaleton/dfinity/agent/AgentBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Exilor Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.scaleton.dfinity.agent; 18 | 19 | import java.time.Duration; 20 | import java.util.Optional; 21 | 22 | import com.scaleton.dfinity.agent.identity.Identity; 23 | 24 | 25 | public class AgentBuilder { 26 | AgentConfig config = new AgentConfig(); 27 | 28 | /** 29 | * Create an instance of [Agent] with the information from this builder. 30 | * @return agent Dfinity agent instance 31 | */ 32 | public Agent build() 33 | { 34 | Agent agent = new Agent(this); 35 | 36 | return agent; 37 | } 38 | 39 | public AgentBuilder transport(ReplicaTransport transport) 40 | { 41 | this.config.transport = Optional.of(transport); 42 | return this; 43 | } 44 | 45 | /** 46 | * Provides a _default_ ingress expiry. This is the delta that will be applied 47 | * at the time an update or query is made. The default expiry cannot be a 48 | * fixed system time. 49 | * @param duration default ingress expiry 50 | */ 51 | 52 | public AgentBuilder ingresExpiry(Duration duration) 53 | { 54 | this.config.ingressExpiryDuration = Optional.of(duration); 55 | return this; 56 | } 57 | 58 | /* 59 | * Add an identity provider for signing messages. This is required. 60 | * @param identity identity provider 61 | */ 62 | public AgentBuilder identity(Identity identity) 63 | { 64 | this.config.identity = identity; 65 | return this; 66 | } 67 | 68 | /* 69 | * Add a NonceFactory to this Agent. By default, no nonce is produced. 70 | */ 71 | 72 | public AgentBuilder nonceFactory(NonceFactory nonceFactory) 73 | { 74 | this.config.nonceFactory = nonceFactory; 75 | return this; 76 | } 77 | 78 | 79 | 80 | } 81 | -------------------------------------------------------------------------------- /src/main/java/com/scaleton/dfinity/agent/AgentConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Exilor Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.scaleton.dfinity.agent; 18 | 19 | import java.time.Duration; 20 | import java.util.Optional; 21 | 22 | import com.scaleton.dfinity.agent.identity.AnonymousIdentity; 23 | import com.scaleton.dfinity.agent.identity.Identity; 24 | 25 | /** 26 | * A configuration for an agent. 27 | */ 28 | class AgentConfig 29 | { 30 | AgentConfig() 31 | { 32 | } 33 | 34 | Optional transport = Optional.empty(); 35 | Optional ingressExpiryDuration = Optional.empty(); 36 | Identity identity = new AnonymousIdentity(); 37 | NonceFactory nonceFactory = new NonceFactory(); 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/scaleton/dfinity/agent/AgentError.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Exilor Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.scaleton.dfinity.agent; 18 | 19 | import java.text.MessageFormat; 20 | import java.util.ResourceBundle; 21 | 22 | public final class AgentError extends Error { 23 | /** 24 | * 25 | */ 26 | private static final long serialVersionUID = 1L; 27 | 28 | final static String RESOURCE_BUNDLE_FILE = "dfinity_agent"; 29 | static ResourceBundle properties; 30 | 31 | AgentErrorCode code; 32 | 33 | 34 | static { 35 | properties = ResourceBundle.getBundle(RESOURCE_BUNDLE_FILE); 36 | } 37 | 38 | public static AgentError create(AgentErrorCode code, Object... args) { 39 | 40 | String message = properties.getString(code.label); 41 | // set arguments 42 | message = MessageFormat.format(message, args); 43 | 44 | return new AgentError(code, message); 45 | } 46 | 47 | public static AgentError create(AgentErrorCode code,Throwable t, Object... args) { 48 | 49 | String message = properties.getString(code.label); 50 | // set arguments 51 | message = MessageFormat.format(message, args); 52 | 53 | return new AgentError(code,t, message); 54 | } 55 | 56 | private AgentError(AgentErrorCode code, String message) { 57 | super(message); 58 | } 59 | 60 | private AgentError(AgentErrorCode code, Throwable t, String message) { 61 | super(message, t); 62 | } 63 | 64 | public AgentErrorCode getCode() { 65 | return code; 66 | } 67 | 68 | public enum AgentErrorCode { 69 | INVALID_REPLICA_URL("InvalidReplicaUrl"), 70 | TIMEOUT_WAITING_FOR_RESPONSE("TimeoutWaitingForResponse"), 71 | URL_SYNTAX_ERROR("UrlSyntaxError"), 72 | URL_PARSE_ERROR("UrlParseError"), 73 | PRINCIPAL_ERROR("PrincipalError"), 74 | REPLICA_ERROR("ReplicaError"), 75 | INVALID_CBOR_DATA("InvalidCborData"), 76 | HTTP_ERROR("HttpError"), 77 | CANNOT_USE_AUTHENTICATION_ON_NONSECURE_URL("CannotUseAuthenticationOnNonSecureUrl"), 78 | AUTHENTICATION_ERROR("AuthenticationError"), 79 | INVALID_REPLICA_STATUS("InvalidReplicaStatus"), 80 | REQUEST_STATUS_DONE_NO_REPLY("RequestStatusDoneNoReply"), 81 | MESSAGE_ERROR("MessageError"), 82 | CUSTOM_ERROR("CustomError"), 83 | LEB128_READ_ERROR("Leb128ReadError"), 84 | UTF8_READ_ERROR("Utf8ReadError"), 85 | LOOKUP_PATH_ABSENT("LookupPathAbsent"), 86 | LOOKUP_PATH_UNKNOWN("LookupPathUnknown"), 87 | LOOKUP_PATH_ERROR("LookupPathError"), 88 | INVALID_REQUEST_STATUS("InvalidRequestStatus"), 89 | CERTIFICATE_VERIFICATION_FAILED("CertificateVerificationFailed"), 90 | NO_ROOT_KEY_IN_STATUS("NoRootKeyInStatus"), 91 | COULD_NOT_READ_ROOT_KEY("CouldNotReadRootKey"), 92 | MISSING_REPLICA_TRANSPORT("MissingReplicaTransport"), 93 | TRANSPORT_ERROR("TransportError"); 94 | 95 | public String label; 96 | 97 | AgentErrorCode(String label) { 98 | this.label = label; 99 | } 100 | 101 | } 102 | 103 | } 104 | -------------------------------------------------------------------------------- /src/main/java/com/scaleton/dfinity/agent/ByteUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Exilor Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.scaleton.dfinity.agent; 18 | 19 | public final class ByteUtils { 20 | 21 | /* 22 | * Helper function to convert byte array to unsigned int array. 23 | * Makes easier to compare with data in Rust implementation 24 | */ 25 | 26 | public static int[] toUnsignedIntegerArray(byte[] input) 27 | { 28 | int[] output = new int[input.length]; 29 | 30 | for(int i = 0; i < input.length; i++) 31 | output[i] = Byte.toUnsignedInt(input[i]); 32 | 33 | return output; 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/scaleton/dfinity/agent/MethodType.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Exilor Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.scaleton.dfinity.agent; 18 | 19 | enum MethodType { 20 | QUERY,UPDATE 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/scaleton/dfinity/agent/NonceFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Exilor Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.scaleton.dfinity.agent; 18 | 19 | import java.security.SecureRandom; 20 | 21 | public final class NonceFactory { 22 | 23 | public byte[] generate() 24 | { 25 | byte[] nonce = new byte[16]; 26 | 27 | new SecureRandom().nextBytes(nonce); 28 | 29 | return nonce; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/scaleton/dfinity/agent/QueryBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Exilor Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.scaleton.dfinity.agent; 18 | 19 | import java.time.Duration; 20 | import java.time.LocalDateTime; 21 | import java.time.ZoneOffset; 22 | import java.util.Optional; 23 | import java.util.concurrent.CompletableFuture; 24 | 25 | import org.apache.commons.lang3.ArrayUtils; 26 | 27 | import com.scaleton.dfinity.types.Principal; 28 | 29 | /* 30 | * A Query Request Builder. 31 | * This makes it easier to do query calls without actually passing all arguments. 32 | */ 33 | 34 | public final class QueryBuilder { 35 | Agent agent; 36 | Principal effectiveCanisterId; 37 | Principal canisterId; 38 | String methodName; 39 | byte[] arg; 40 | Optional ingressExpiryDatetime; 41 | 42 | QueryBuilder(Agent agent, Principal canisterId,String methodName ) 43 | { 44 | this.agent = agent; 45 | this.canisterId = canisterId; 46 | this.methodName = methodName; 47 | this.effectiveCanisterId = canisterId.clone(); 48 | this.ingressExpiryDatetime = Optional.empty(); 49 | this.arg = ArrayUtils.EMPTY_BYTE_ARRAY; 50 | } 51 | 52 | public static QueryBuilder create(Agent agent, Principal canisterId,String methodName ) 53 | { 54 | return new QueryBuilder(agent, canisterId, methodName); 55 | } 56 | 57 | public QueryBuilder effectiveCanisterId(Principal effectiveCanisterId) 58 | { 59 | this.effectiveCanisterId = effectiveCanisterId; 60 | return this; 61 | } 62 | 63 | public QueryBuilder arg(byte[] arg) 64 | { 65 | this.arg = arg; 66 | return this; 67 | } 68 | 69 | /** 70 | Takes a SystemTime converts it to a Duration by calling 71 | duration_since(UNIX_EPOCH) to learn about where in time this SystemTime lies. 72 | The Duration is converted to nanoseconds and stored in ingressExpiryDatetime 73 | */ 74 | public QueryBuilder expireAt(LocalDateTime time) 75 | { 76 | this.ingressExpiryDatetime = Optional.of(time.toEpochSecond(ZoneOffset.UTC)); 77 | 78 | return this; 79 | } 80 | /** 81 | Takes a Duration (i.e. 30 sec/5 min 30 sec/1 h 30 min, etc.) and adds it to the 82 | Duration of the current SystemTime since the UNIX_EPOCH 83 | Subtracts a permitted drift from the sum to account for using system time and not block time. 84 | Converts the difference to nanoseconds and stores in ingressExpiryDatetime 85 | */ 86 | 87 | public QueryBuilder expireAfter(Duration duration) 88 | { 89 | Duration permittedDrift = Duration.ofSeconds(Agent.DEFAULT_PERMITTED_DRIFT); 90 | 91 | this.ingressExpiryDatetime = Optional.of((Duration.ofMillis(System.currentTimeMillis()).plus(duration).minus(permittedDrift)).toNanos()); 92 | 93 | return this; 94 | } 95 | 96 | /* 97 | * Make a query call. This will return a byte vector. 98 | */ 99 | 100 | public CompletableFuture call() throws AgentError 101 | { 102 | return agent.queryRaw(this.canisterId, this.effectiveCanisterId, this.methodName, this.arg, this.ingressExpiryDatetime); 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /src/main/java/com/scaleton/dfinity/agent/ReplicaTransport.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Exilor Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.scaleton.dfinity.agent; 18 | 19 | import java.util.concurrent.CompletableFuture; 20 | 21 | import com.scaleton.dfinity.agent.requestid.RequestId; 22 | import com.scaleton.dfinity.types.Principal; 23 | 24 | 25 | public interface ReplicaTransport { 26 | 27 | public CompletableFuture status(); 28 | 29 | public CompletableFuture query(Principal canisterId, byte[] envelope); 30 | 31 | public CompletableFuture call(Principal canisterId, byte[] envelope, RequestId requestId); 32 | 33 | public CompletableFuture readState(Principal canisterId, byte[] envelope); 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/scaleton/dfinity/agent/RequestStatusResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Exilor Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.scaleton.dfinity.agent; 18 | 19 | import java.util.Optional; 20 | 21 | import com.scaleton.dfinity.agent.replicaapi.CallReply; 22 | 23 | public final class RequestStatusResponse { 24 | public static final String UNKNOWN_STATUS_VALUE = "unknown"; 25 | public static final String RECEIVED_STATUS_VALUE = "received"; 26 | public static final String PROCESSING_STATUS_VALUE = "processing"; 27 | public static final String REJECTED_STATUS_VALUE = "rejected"; 28 | public static final String REPLIED_STATUS_VALUE = "replied"; 29 | public static final String DONE_STATUS_VALUE = "done"; 30 | 31 | public InnerStatus status; 32 | 33 | public Optional replied; 34 | 35 | public Optional rejected; 36 | 37 | 38 | RequestStatusResponse(InnerStatus status) 39 | { 40 | this.status = status; 41 | } 42 | 43 | RequestStatusResponse(CallReply replied) 44 | { 45 | this.status = InnerStatus.REPLIED_STATUS; 46 | this.replied = Optional.of(replied); 47 | } 48 | 49 | RequestStatusResponse(Integer rejectCode, String rejectMessage) 50 | { 51 | 52 | this.status = InnerStatus.REJECTED_STATUS; 53 | this.rejected = Optional.of(new Rejected(rejectCode, rejectMessage)); 54 | } 55 | 56 | public final class Rejected { 57 | public Integer rejectCode; 58 | public String rejectMessage; 59 | 60 | Rejected(Integer rejectCode, String rejectMessage) 61 | { 62 | this.rejectCode = rejectCode; 63 | this.rejectMessage = rejectMessage; 64 | } 65 | } 66 | 67 | public enum InnerStatus { 68 | UNKNOWN_STATUS(UNKNOWN_STATUS_VALUE), 69 | RECEIVED_STATUS(RECEIVED_STATUS_VALUE), 70 | PROCESSING_STATUS(PROCESSING_STATUS_VALUE), 71 | REJECTED_STATUS(REJECTED_STATUS_VALUE), 72 | REPLIED_STATUS(REPLIED_STATUS_VALUE), 73 | DONE_STATUS(DONE_STATUS_VALUE); 74 | 75 | String value; 76 | 77 | InnerStatus(String value) { 78 | this.value = value; 79 | } 80 | 81 | public String toString() 82 | { 83 | return this.value; 84 | } 85 | 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/main/java/com/scaleton/dfinity/agent/ResponseAuthentication.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Exilor Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.scaleton.dfinity.agent; 18 | 19 | import java.nio.charset.StandardCharsets; 20 | import java.util.ArrayList; 21 | import java.util.List; 22 | 23 | import com.scaleton.dfinity.agent.hashtree.Label; 24 | import com.scaleton.dfinity.agent.hashtree.LookupResult; 25 | import com.scaleton.dfinity.agent.replicaapi.CallReply; 26 | import com.scaleton.dfinity.agent.replicaapi.Certificate; 27 | import com.scaleton.dfinity.agent.requestid.RequestId; 28 | import com.scaleton.dfinity.candid.Leb128; 29 | 30 | public final class ResponseAuthentication { 31 | 32 | static RequestStatusResponse lookupRequestStatus(Certificate certificate, RequestId requestId) throws AgentError 33 | { 34 | List