{"templateId":"markdown","versions":[{"version":"v1.43","label":"v1.43 LTS","link":"/products/custody/developer-experience/sdks/migrate-from-legacy-java-sdk","default":true,"active":true,"folderId":"c15a2701"},{"version":"v1.42","label":"v1.42 STS","link":"/products/custody/v1.42/developer-experience/sdks/migrate-from-legacy-java-sdk","default":false,"active":false,"folderId":"c15a2701"},{"version":"v1.41","label":"v1.41 STS","link":"/products/custody/v1.41/developer-experience/sdks/migrate-from-legacy-java-sdk","default":false,"active":false,"folderId":"c15a2701"},{"version":"v1.34","label":"v1.34 LTS","link":"/products/custody/v1.34/developer-experience/sdks/migrate-from-legacy-java-sdk","default":false,"active":false,"folderId":"c15a2701"},{"version":"v1.26","label":"v1.26 LTS","link":"/products/custody/v1.26/developer-experience/sdks/migrate-from-legacy-java-sdk","default":false,"active":false,"folderId":"c15a2701"},{"version":"v1.19","label":"v1.19 LTS","link":"/products/custody/v1.19/developer-experience/sdks/migrate-from-legacy-java-sdk","default":false,"active":false,"folderId":"c15a2701"},{"version":"v1.15","label":"v1.15 LTS","link":"/products/custody/v1.15/developer-experience/sdks/migrate-from-legacy-java-sdk","default":false,"active":false,"folderId":"c15a2701"}],"sharedDataIds":{"sidebar":"sidebar-products/custody/@v1.15/sidebars.yaml"},"props":{"metadata":{"markdoc":{"tagList":["tabs","tab","admonition"]},"type":"markdown"},"seo":{"title":"Migrate from the legacy Java SDK","description":"User guides, API reference, and support resources.","siteUrl":"https://docs.ripple.com","lang":"en-US"},"dynamicMarkdocComponents":[],"compilationErrors":[],"ast":{"$$mdtype":"Tag","name":"article","attributes":{},"children":[{"$$mdtype":"Tag","name":"Heading","attributes":{"level":1,"id":"migrate-from-the-legacy-java-sdk","__idx":0},"children":["Migrate from the legacy Java SDK"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The ","Ripple Custody"," client SDKs replace the legacy Java SDK (Maven artifact ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["com.metaco:sdk"]},", loaded with ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["HarmonizeContext.load(signer)"]},"). If your application uses the legacy SDK, use this page to move it to the new Java SDK. The page maps legacy concepts, configuration, and calls to the new SDK, and shows before-and-after code for common tasks."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The new SDK is also available for TypeScript and Python, with the same configuration model and intent lifecycle. If you're moving off the legacy SDK anyway, you can choose any of the three. For an overview of all three, see ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/products/custody/developer-experience/sdks"},"children":["SDKs"]},"."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"what-changes","__idx":1},"children":["What changes"]},{"$$mdtype":"Tag","name":"div","attributes":{"className":"md-table-wrapper"},"children":[{"$$mdtype":"Tag","name":"table","attributes":{"className":"md"},"children":[{"$$mdtype":"Tag","name":"thead","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Area"},"children":["Area"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Legacy SDK"},"children":["Legacy SDK"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"New Java SDK"},"children":["New Java SDK"]}]}]},{"$$mdtype":"Tag","name":"tbody","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Dependency"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["com.metaco:sdk"]},", installed from a JAR with ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["mvn install:install-file"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["com.ripple.custody.platform.contrib:ripple-custody-client-lib-java"]},", also installed from a JAR and a Project Object Model (POM) file with ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["mvn install:install-file"]},". Requires Java 17 or later"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Package root"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["com.metaco.harmonize"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["com.ripple.custody"]}]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Configuration"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["harmonize.json"]}," file or environment variables (",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["GATEWAY_URL"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["OAUTH_URL"]},", and others)"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["config.toml"]}," file or ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["RC_*"]}," environment variables. Environment variables override the file"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Entry point"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["HarmonizeContext.load(signer)"]},", then ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["harmonizeCtx.harmonize"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["CustodyClient.fromConfig(CustodyClientConfig.loadConfiguration())"]}]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Signing"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["You implement the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Signer"]}," interface"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Built-in signer for a PEM private key file, or your own ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["ChallengeSigner"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["IntentSigner"]}]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Intent author"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Derived from the signer"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Set with ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["RC_USER_ID"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["RC_DOMAIN_ID"]}," or ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["config.author(...)"]},", or looked up through ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["GET /v1/me"]}]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Resource access"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Action classes per call, for example ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["harmonize.users(domainId)"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Fixed namespaces on one client, for example ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["client.governance().users()"]},", with the domain ID passed to each method"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["IDs"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["String"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["java.util.UUID"]}]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Entity creation and updates"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Fluent builders ending in ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":[".submit()"]},", returning ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["IntentData"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Namespace methods that build, sign, and submit the intent, returning ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["PendingIntent"]}]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Waiting for results"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["waitForSucceed"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["waitForIntentStatus"]},", and resource-specific waits, with a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Timeout"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["waitAccepted"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["waitExecuted"]},", and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["waitTxHash"]},", with a timeout in seconds"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Proposal expiry"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Set per call with ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Expire"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Fixed at one hour from submission"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Errors"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["RuntimeException"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["CustodyError"]}," (unchecked), with the HTTP ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["ApiException"]}," as its cause"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Response signatures"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Not verified"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The SDK verifies them by default, which requires the notary API public key"]}]}]}]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["To install the new SDK, get the JAR and POM files from the ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/products/custody/support/get-support"},"children":["Ripple support team"]},". For full installation and setup steps, see ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/products/custody/get-started/integrate-via-sdk#install-the-sdk"},"children":["Integrate via SDK"]},"."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Install the files into your local Maven repository, as you did for the legacy SDK. Replace ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["{version}"]}," with the version you received:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"bash","header":{"controls":{"copy":{}}},"source":"mvn install:install-file \\\n  -Dfile=ripple-custody-client-lib-java-{version}.jar \\\n  -DpomFile=ripple-custody-client-lib-java-{version}.pom\n","lang":"bash"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Then replace the legacy dependency with the new one:"]},{"$$mdtype":"Tag","name":"Tabs","attributes":{"size":"medium"},"children":[{"$$mdtype":"Tag","name":"TabItemFragment","attributes":{"label":"Gradle","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"groovy","header":{"controls":{"copy":{}}},"source":"repositories {\n    mavenLocal()\n    mavenCentral()\n}\n\ndependencies {\n    implementation 'com.ripple.custody.platform.contrib:ripple-custody-client-lib-java:{version}'\n}\n","lang":"groovy"},"children":[]}]},{"$$mdtype":"Tag","name":"TabItemFragment","attributes":{"label":"Maven","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"xml","header":{"controls":{"copy":{}}},"source":"<dependency>\n    <groupId>com.ripple.custody.platform.contrib</groupId>\n    <artifactId>ripple-custody-client-lib-java</artifactId>\n    <version>{version}</version>\n</dependency>\n","lang":"xml"},"children":[]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"map-your-configuration","__idx":2},"children":["Map your configuration"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The legacy SDK read ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["harmonize.json"]}," from the home directory, the working directory, the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["--conf"]}," flag, or ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["HARMONIZE_CONF"]},", then applied environment variables. The new SDK reads the file named by ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["RC_CONFIG_FILE"]},", or ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["./config.toml"]}," if it exists, then applies ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["RC_*"]}," environment variables, which take precedence."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The following table maps each legacy key to its replacement:"]},{"$$mdtype":"Tag","name":"div","attributes":{"className":"md-table-wrapper"},"children":[{"$$mdtype":"Tag","name":"table","attributes":{"className":"md"},"children":[{"$$mdtype":"Tag","name":"thead","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Legacy key"},"children":["Legacy key"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"New environment variable"},"children":["New environment variable"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"New config.toml key"},"children":["New ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["config.toml"]}," key"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Notes"},"children":["Notes"]}]}]},{"$$mdtype":"Tag","name":"tbody","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["HARMONIZE_CONF"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["RC_CONFIG_FILE"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Not applicable"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Path to the configuration file. The new SDK has no home-directory lookup and no ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["--conf"]}," flag."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["GATEWAY_URL"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["RC_API_BASE_URL"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["api_base_url"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Base URL of the ","Ripple Custody"," API."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["OAUTH_URL"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["RC_TOKEN_ENDPOINT"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["token_endpoint"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["OAuth 2.0 token endpoint. To have the SDK discover the token endpoint, set ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["RC_OIDC_ISSUER_URL"]}," (",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["oidc_issuer_url"]},") instead."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["OAUTH_CLIENT_ID"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["RC_CLIENT_ID"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["client_id"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Defaults to ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["customer_api"]}," when you sign with a private key."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Not applicable (the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Signer"]}," implementation)"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["RC_PRIVATE_KEY_FILE"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["private_key_file"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Path to the user's EC private key in PEM format. See ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"#replace-your-signer"},"children":["Replace your signer"]},"."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Not applicable"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["RC_USER_ID"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["rc_user_id"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["ID of the user that authors intents."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Not applicable"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["RC_DOMAIN_ID"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["rc_domain_id"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Default domain of the authoring user."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Not applicable"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["RC_NOTARY_API_PUBLIC_KEY"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["notary_api_public_key"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The SDK requires this key while response verification is on. See ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"#behavior-differences"},"children":["Behavior differences"]},"."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Not applicable"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["RC_VERIFY_RESPONSES"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["verify_responses"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["true"]}," by default."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["TIMEOUT"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["None"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["None"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Set timeouts on the underlying HTTP client, for example ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["client.getApiClient().setReadTimeout(milliseconds)"]}," or ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["setConnectTimeout(milliseconds)"]},"."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["HTTP_VERSION"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["None"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["None"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["To control the HTTP client, pass your own ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["OkHttpClient"]}," to ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["ApiClient.newBuilder().httpClient(...)"]},"."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["OPEN_API_VALIDATE_WARN_ONLY"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["OPEN_API_VALIDATE_STRICT_ENUMS"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["None"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["None"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The new SDK doesn't check requests for conformance with the OpenAPI document at runtime."]}]}]}]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The new SDK also supports the client credentials grant (",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["RC_CLIENT_ID"]}," with ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["RC_CLIENT_SECRET"]},"), TLS settings, and address validation options. For the full list, see ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/products/custody/developer-experience/sdks/configuration"},"children":["Configure the SDK"]},"."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The following example converts a legacy ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["harmonize.json"]}," file:"]},{"$$mdtype":"Tag","name":"Tabs","attributes":{"size":"medium"},"children":[{"$$mdtype":"Tag","name":"TabItemFragment","attributes":{"label":"Legacy SDK","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{\n  \"GATEWAY_URL\": \"https://custody.example.com/api\",\n  \"OAUTH_URL\": \"https://custody.example.com/oauth/token\",\n  \"OAUTH_CLIENT_ID\": \"customer_api\"\n}\n","lang":"json"},"children":[]}]},{"$$mdtype":"Tag","name":"TabItemFragment","attributes":{"label":"Java SDK","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"toml","header":{"controls":{"copy":{}}},"source":"api_base_url = \"https://custody.example.com/api\"\ntoken_endpoint = \"https://custody.example.com/oauth/token\"\nclient_id = \"customer_api\"\nprivate_key_file = \"/path/to/signing-key.pem\"\nrc_domain_id = \"<domain-id>\"\nrc_user_id = \"<user-id>\"\nnotary_api_public_key = \"<notary-api-public-key>\"\n","lang":"toml"},"children":[]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"load-the-configuration-and-create-a-client","__idx":3},"children":["Load the configuration and create a client"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["A single ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["CustodyClientConfig"]}," and a long-lived ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["CustodyClient"]}," replace the legacy ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["HarmonizeContext"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Context"]},", and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["harmonize"]}," instance. ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["CustodyClient.fromConfig"]}," resolves the signer, obtains OAuth tokens, and configures the HTTP client for you."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The following example creates a client with each SDK:"]},{"$$mdtype":"Tag","name":"Tabs","attributes":{"size":"medium"},"children":[{"$$mdtype":"Tag","name":"TabItemFragment","attributes":{"label":"Legacy SDK","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"java","header":{"controls":{"copy":{}}},"source":"var harmonizeCtx = HarmonizeContext.load(signer);\n// we get the Ripple Custody instance from the context\nvar harmonize = harmonizeCtx.harmonize;\n","lang":"java"},"children":[]}]},{"$$mdtype":"Tag","name":"TabItemFragment","attributes":{"label":"Java SDK","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"java","header":{"controls":{"copy":{}}},"source":"import com.ripple.custody.CustodyClient;\nimport com.ripple.custody.CustodyClientConfig;\n\nCustodyClientConfig config = CustodyClientConfig.loadConfiguration();\nCustodyClient client = CustodyClient.fromConfig(config);\n","lang":"java"},"children":[]}]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["For a complete program, see example ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["00"]}," (getting started). To get the examples, see ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/products/custody/developer-experience/sdks#examples"},"children":["Examples"]},"."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["To load a specific file instead of ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["RC_CONFIG_FILE"]}," or ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["./config.toml"]},", call ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["CustodyClientConfig.loadConfiguration(Path.of(\"/path/to/config.toml\"))"]},". To read environment variables only, call ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["CustodyClientConfig.fromEnvironment()"]},"."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The legacy ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["harmonizeCtx.switchSigner(newSigner)"]}," has no replacement in the new SDK. To act as a different user, create a second ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["CustodyClientConfig"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["CustodyClient"]}," with that user's key and IDs."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"replace-your-signer","__idx":4},"children":["Replace your signer"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The legacy SDK required you to implement the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Signer"]}," interface and to serialize each message to canonical JSON before signing it. The new SDK canonicalizes every request for you and offers two signing options."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Private key file."]}," If your user's private key is available as a PEM file, set ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["RC_PRIVATE_KEY_FILE"]}," (or ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["private_key_file"]},"). The SDK uses the key both to sign the OAuth login challenge and to sign intents. You don't write any signing code."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Your own key management system."]}," If the key lives in a hardware security module (HSM) or a key management service, implement two signing callbacks and build the client yourself:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["com.ripple.custody.auth.ChallengeSigner"]}," signs the OAuth login challenge and returns the user's public key."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["com.ripple.custody.IntentSigner"]}," signs the canonical JSON of each intent, approval, and rejection. It receives the canonical JSON string and returns a base64-encoded signature."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["In the following example, ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["myKeyService"]}," stands for your own integration with your key management system:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"java","header":{"controls":{"copy":{}}},"source":"import com.ripple.custody.CustodyClient;\nimport com.ripple.custody.CustodyClientConfig;\nimport com.ripple.custody.auth.ChallengeSigner;\nimport com.ripple.custody.invoker.ApiClient;\n\nCustodyClientConfig config = CustodyClientConfig.loadConfiguration();\n\nChallengeSigner challengeSigner = new ChallengeSigner(\n        challenge -> myKeyService.sign(challenge),          // base64 signature\n        unused -> myKeyService.publicKeyBase64Der());       // base64 DER public key\n\nApiClient apiClient = ApiClient.newBuilder()\n        .tokenEndpoint(config.getEffectiveTokenEndpoint())\n        .clientId(\"customer_api\")\n        .grantType(\"password\")\n        .signer(challengeSigner)\n        .build();\napiClient.setBasePath(config.getApiBaseUrl());\n\nconfig.apiClient(apiClient)\n        .signer(canonicalJson -> myKeyService.sign(canonicalJson));\n\nCustodyClient client = new CustodyClient(config);\n","lang":"java"},"children":[]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"info","name":"KMS providers"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The Java SDK doesn't include signers for cloud key management services or HashiCorp Vault. Setting ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["RC_KMS_PROVIDER"]}," makes ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["CustodyClient.fromConfig"]}," fail. Use custom ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["ChallengeSigner"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["IntentSigner"]}," callbacks, as shown in the preceding example. The Java examples ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Example08HashiCorpVaultTransit"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Example09AzureKeyVaultKeys"]},", and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Example10AwsKms"]}," show a signer for each provider. For details, see ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/products/custody/developer-experience/sdks/authentication-and-signing"},"children":["Authentication and signing"]},"."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"map-classes-and-methods","__idx":5},"children":["Map classes and methods"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Each legacy action class maps to a namespace on ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["CustodyClient"]},", as the following table shows. Namespace accessors are methods. Where the API requires a domain ID, every namespace method takes it as its first argument."]},{"$$mdtype":"Tag","name":"div","attributes":{"className":"md-table-wrapper"},"children":[{"$$mdtype":"Tag","name":"table","attributes":{"className":"md"},"children":[{"$$mdtype":"Tag","name":"thead","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Legacy SDK"},"children":["Legacy SDK"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"New Java SDK"},"children":["New Java SDK"]}]}]},{"$$mdtype":"Tag","name":"tbody","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["HarmonizeContext.load(signer)"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["CustodyClient.fromConfig(CustodyClientConfig.loadConfiguration())"]}]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Config"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["CustodyClientConfig"]}]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Signer"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["ChallengeSigner"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["IntentSigner"]},", or ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["RC_PRIVATE_KEY_FILE"]}]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["harmonize.domains()"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["client.governance().domains()"]}]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["harmonize.users(domainId)"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["client.governance().users()"]}]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["harmonize.policies(domainId)"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["client.governance().policies()"]}]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["harmonize.tickers()"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["client.governance().tickers()"]}]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["harmonize.intents(domainId)"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["client.governance().intents()"]}]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["harmonize.requests(domainId)"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["client.governance().requests()"]}]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["harmonize.events(domainId)"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["client.governance().events()"]}]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["harmonize.accounts(domainId)"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["client.accounts()"]}]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["harmonize.vaults()"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["client.vaults()"]}]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["harmonize.endpoints(domainId)"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["client.endpoints()"]}]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["harmonize.ledgers()"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["client.ledgers()"]}]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["harmonize.transactions(domainId)"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["client.transactions()"]}]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["harmonize.genesis()"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["client.genesis()"]}]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["harmonize.me()"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["No namespace method. Call ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["new UsersApi(client.getApiClient()).getMe()"]},"."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["harmonize.notarize()"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["No namespace method. Use the generated ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["IntentsApi"]}," directly."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":[".get(id)"]}," returning ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Optional"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["get(domainId, id)"]}," throws ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["CustodyError"]}," if the entity doesn't exist. ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["find(domainId, id)"]}," returns ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Optional"]}]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":[".list()"]}," returning a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Stream"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["stream(domainId)"]}," pages through all results. ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["list(domainId, limit, startingAfter)"]}," returns one page"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":[".create()...submit()"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":[".create(entity, expire)"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["create(...)"]}," on the namespace, returning ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["PendingIntent"]}]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":[".update(...)"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":[".lock(...)"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":[".unlock(...)"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["update(...)"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["lock(...)"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["unlock(...)"]}," on the namespace, returning ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["PendingIntent"]},". Overloads accept a fetched entity"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["IntentData"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["PendingIntent"]}]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["IntentData.getIntentId()"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["PendingIntent.getIntentId()"]},", available after ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["waitAccepted"]}]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["waitForSucceed(Timeout)"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["waitForProcessingOrSucceeded(Timeout)"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["waitAccepted(timeoutSeconds)"]}]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["waitForIntentStatus(Set.of(IntentStatus.Executed), Timeout)"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["waitExecuted(timeoutSeconds)"]}]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["TransactionIntentData.waitForOrderTransactionProcessingStatus(...)"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["waitTxHash(timeoutSeconds)"]}]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["harmonize.intents(domainId).approve(intentId, expire)"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["pendingIntent.approve(comment)"]},", or ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["client.governance().intents().approve(domainId, intentId, proposalSignature, comment)"]}]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["harmonize.intents(domainId).reject(intentId, reason, expire)"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["pendingIntent.reject(comment)"]},", or ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["client.governance().intents().reject(domainId, intentId, proposalSignature, comment)"]}]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["MapJSON"]}," ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["get(Class, key)"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["set(key, value)"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Typed model classes in ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["com.ripple.custody.models"]},", each with ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["getAdditionalProperties()"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["putAdditionalProperty(key, value)"]}," for fields the model doesn't declare"]}]}]}]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The new SDK also has a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["client.webhooks()"]}," namespace for webhook channels, which the legacy SDK didn't offer."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"track-intents-with-pendingintent","__idx":6},"children":["Track intents with PendingIntent"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["In the legacy SDK, each action returned an ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["IntentData"]}," and you chained a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["waitFor..."]}," method to poll the request and then the intent. In the new SDK, every method that proposes an intent signs and submits it, and returns a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["PendingIntent"]},":"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["waitAccepted(timeoutSeconds)"]}," polls the request until ","Ripple Custody"," accepts or rejects it, and records the intent ID. It throws ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["CustodyError"]}," if the request fails. Call it first."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["waitExecuted(timeoutSeconds)"]}," polls the intent until it reaches a terminal status: ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Executed"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Failed"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Rejected"]},", or ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Expired"]},"."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["waitTxHash(timeoutSeconds)"]}," supports transfer and transaction-order intents. It polls until the on-chain transaction reaches ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Completed"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Failed"]},", or ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Interrupted"]},"."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["If the timeout elapses first, the wait methods throw ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["IntentTimeoutError"]},". A timeout isn't a failure verdict: the intent might still execute later. If an intent needs approval from other users, don't block on ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["waitExecuted"]},". Check the intent later with ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["client.governance().intents().get(domainId, intentId)"]},"."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["For more on the intent lifecycle, see ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/products/custody/developer-experience/sdks/intents"},"children":["Intents"]},"."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"common-tasks-before-and-after","__idx":7},"children":["Common tasks before and after"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The examples in this section assume a configured ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["client"]},", as shown in ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"#load-the-configuration-and-create-a-client"},"children":["Load the configuration and create a client"]},"."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"create-a-user","__idx":8},"children":["Create a user"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The new ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["create"]}," method requires at least one login ID and a public key in base64 DER format. It validates both before it sends the request. The following example creates a user with each SDK:"]},{"$$mdtype":"Tag","name":"Tabs","attributes":{"size":"medium"},"children":[{"$$mdtype":"Tag","name":"TabItemFragment","attributes":{"label":"Legacy SDK","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"java","header":{"controls":{"copy":{}}},"source":"var domainId = \"\";\nvar userId = \"\";\nvar userAlias = \"\";\nvar userRoles = List.of(\"admin\");\nvar userPublicKey = \"\";\nvar userDescription = \"\";\n\nvar user = Users.CreateUser.builder()\n        .id(userId)\n        .alias(userAlias)\n        .description(userDescription)\n        .roles(userRoles)\n        .publicKey(userPublicKey)\n        .build();\n\nharmonize.users(domainId)\n        .create(user, Expire.hours(24))\n        .waitForSucceed(Timeout.minutes(1));\n","lang":"java"},"children":[]}]},{"$$mdtype":"Tag","name":"TabItemFragment","attributes":{"label":"Java SDK","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"java","header":{"controls":{"copy":{}}},"source":"UUID domainId = UUID.fromString(\"<domain-id>\");\nString userAlias = \"<user-alias>\";\nString userPublicKey = \"<base64-der-public-key>\";\n\nPendingIntent pending = client.governance().users().create(\n        domainId,\n        null,                       // user ID; null generates one\n        userAlias,\n        userPublicKey,\n        List.of(\"admin\"),\n        List.of(new CoreLoginId().id(userAlias).providerId(\"internal\")),\n        Map.of());\n\npending.waitAccepted(60);\nvar intent = pending.waitExecuted(120);\nif (!\"Executed\".equals(String.valueOf(intent.getData().getState().getStatus()))) {\n    throw new IllegalStateException(\"Intent did not execute: \" + intent.getData().getState().getStatus());\n}\n","lang":"java"},"children":[]}]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["For a complete program, see example ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["10"]}," (create user). To get the examples, see ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/products/custody/developer-experience/sdks#examples"},"children":["Examples"]},"."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["To create a domain, the new Java SDK has no ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["create"]}," method on ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["client.governance().domains()"]},". Build a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["CoreV0CreateDomain"]}," payload and submit it with ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Envelope.submitIntent(client.getConfig(), payload, parentDomainId, null)"]},", which returns a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["PendingIntent"]},"."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"create-a-transfer","__idx":9},"children":["Create a transfer"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The legacy ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["TransactionActions"]}," builder maps to ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["client.transactions().transfer(...)"]}," for transfers. When you need chain-specific transaction parameters, use ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["client.transactions().createTransactionOrder(...)"]}," instead. A transfer names the ticker to send rather than a chain-specific parameter builder. The following example creates a transfer with each SDK:"]},{"$$mdtype":"Tag","name":"Tabs","attributes":{"size":"medium"},"children":[{"$$mdtype":"Tag","name":"TabItemFragment","attributes":{"label":"Legacy SDK","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"java","header":{"controls":{"copy":{}}},"source":"var domainId = \"\";\nvar fromAccount = \"\";\nvar toAccount = \"\";\nvar amount = \"5432\";\nvar maxFee = \"5432\";\n\nvar transaction = Transactions.CreateTransactionOrder.builder()\n        .fromAccount(fromAccount)\n        .orderParameters(Transactions.btcParameters()\n                .maxFee(maxFee)\n                .priorityHigh()\n                .toAccount(domainId, toAccount)\n                .amount(amount)\n                .build()\n        )\n        .build();\n\nharmonize.transactions(domainId).create(transaction, Expire.hours(24))\n        .waitForSucceed(Timeout.minutes(1));\n","lang":"java"},"children":[]}]},{"$$mdtype":"Tag","name":"TabItemFragment","attributes":{"label":"Java SDK","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"java","header":{"controls":{"copy":{}}},"source":"CoreCreateTransferOrderOutput output = new CoreCreateTransferOrderOutput()\n        .destination(new CoreTransactionDestination(\n                new CoreTransactionDestinationAccount()\n                        .accountId(toAccountId)\n                        .type(CoreTransactionDestinationAccount.TypeEnum.ACCOUNT)))\n        .amount(\"5432\");\n\nPendingIntent pending = client.transactions().transfer(\n        domainId, fromAccountId, tickerId, List.of(output),\n        CoreFeePriority.HIGH, \"5432\", null, Map.of());\n\npending.waitAccepted(60);\nvar intent = pending.waitExecuted(120);\nif (!\"Executed\".equals(String.valueOf(intent.getData().getState().getStatus()))) {\n    throw new IllegalStateException(\"Intent did not execute: \" + intent.getData().getState().getStatus());\n}\nCoreApiTransaction tx = pending.waitTxHash(600);\n","lang":"java"},"children":[]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"approve-an-intent","__idx":10},"children":["Approve an intent"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["If you proposed the intent in the same process, approve it through the returned ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["PendingIntent"]},", which already holds the proposal signature. To approve an intent that someone else proposed, read the proposal signature from the intent and pass it to ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["client.governance().intents().approve(...)"]},". To reject an intent, use ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["reject"]}," the same way. The following example approves an intent with each SDK:"]},{"$$mdtype":"Tag","name":"Tabs","attributes":{"size":"medium"},"children":[{"$$mdtype":"Tag","name":"TabItemFragment","attributes":{"label":"Legacy SDK","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"java","header":{"controls":{"copy":{}}},"source":"var domain = harmonize.domains().get(domainId).orElseThrow();\n\nharmonize.intents(domain.getId())\n        .approve(intentData.getIntentId(),\n        Expire.hours(1))\n        .waitForSucceed(Timeout.minutes(1));\n\nIntents.IntentEntity intent = harmonize.intents(domain.getId()).get(intentData.getIntentId()).orElseThrow();\n","lang":"java"},"children":[]}]},{"$$mdtype":"Tag","name":"TabItemFragment","attributes":{"label":"Java SDK","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"java","header":{"controls":{"copy":{}}},"source":"// Approve an intent you proposed\npending.waitAccepted(60);\npending.approve(\"Approved by treasury service\");\npending.waitExecuted(120);\n\n// Approve an intent proposed by another user\nCoreTrustedIntent intent = client.governance().intents().get(domainId, intentId);\nString proposalSignature = intent.getData().getDetails().getProposalSignature();\nclient.governance().intents().approve(\n        domainId, intentId, proposalSignature, \"Approved by treasury service\");\n","lang":"java"},"children":[]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"behavior-differences","__idx":11},"children":["Behavior differences"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["These differences change runtime behavior, not only names. Check each one before you switch over."]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["The SDK verifies response signatures by default."]}," The new SDK checks the notary signature on API responses and throws ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["ResponseSignatureError"]}," if verification fails. Creating a client fails unless you set ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["RC_NOTARY_API_PUBLIC_KEY"]}," (or ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["config.notaryApiPublicKey(...)"]},"), or explicitly opt out with ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["RC_VERIFY_RESPONSES=false"]}," (or ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["config.verifyResponses(false)"]},"). Get the notary API public key for your environment from your ","Ripple Custody"," administrator. For details, see ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/products/custody/developer-experience/sdks/response-verification"},"children":["Response verification"]},"."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["The SDK handles canonical JSON for you."]}," You no longer call ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["toJson()"]}," or ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["GsonUtils"]}," before signing. An ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["IntentSigner"]}," receives the canonical JSON string and signs it as is."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["No automatic retries."]}," The SDK doesn't retry failed HTTP requests. Add your own retry logic where your application needs it, and make sure retried intent submissions are safe to repeat. For details, see ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/products/custody/developer-experience/sdks/errors-and-http"},"children":["Errors and HTTP"]},"."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Every intent must have an author."]}," Set ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["RC_USER_ID"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["RC_DOMAIN_ID"]},", or call ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["config.author(...)"]}," with a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["CoreUserReference"]},". Otherwise, the SDK looks up your user through ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["GET /v1/me"]},". If you belong to several domains, set ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["RC_DOMAIN_ID"]},"."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Waiting for execution doesn't throw on a failed intent."]}," ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["waitExecuted"]}," returns the intent when it reaches any terminal status: ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Executed"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Failed"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Rejected"]},", or ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Expired"]},". Check ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["pending.getStatus()"]}," or the returned intent's state. The legacy ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["waitFor"]}," methods threw a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["RuntimeException"]}," for failure states."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Proposals have a fixed expiry."]}," Intents that you propose through the new SDK expire one hour after submission. The new SDK has no ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Expire"]}," argument."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Updates replace list fields."]}," ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["update"]}," methods on users, policies, endpoints, and tickers replace list fields such as roles, login IDs, and workflow conditions in full. Read the current entity and pass its existing values back unless you intend to remove them."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Address validation is on by default."]}," Before it sends the request, ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["transfer"]}," rejects a destination address that isn't in a recognized format for any supported chain. To turn this off, set ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["RC_VALIDATE_ADDRESSES=false"]},"."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"next-steps","__idx":12},"children":["Next steps"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/products/custody/get-started/integrate-via-sdk"},"children":["Integrate via SDK"]},": install the SDK, connect, and submit a first intent."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/products/custody/developer-experience/sdks/configuration"},"children":["Configure the SDK"]},": all configuration keys and environment variables."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/products/custody/developer-experience/sdks/authentication-and-signing"},"children":["Authentication and signing"]},": grants, private keys, and custom signers."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/products/custody/developer-experience/sdks/intents"},"children":["Intents"]},": propose, approve, reject, and track intents."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/products/custody/developer-experience/sdks/errors-and-http"},"children":["Errors and HTTP"]},": error types, timeouts, and custom HTTP clients."]}]}]},"headings":[{"value":"Migrate from the legacy Java SDK","id":"migrate-from-the-legacy-java-sdk","depth":1},{"value":"What changes","id":"what-changes","depth":2},{"value":"Map your configuration","id":"map-your-configuration","depth":2},{"value":"Load the configuration and create a client","id":"load-the-configuration-and-create-a-client","depth":2},{"value":"Replace your signer","id":"replace-your-signer","depth":2},{"value":"Map classes and methods","id":"map-classes-and-methods","depth":2},{"value":"Track intents with PendingIntent","id":"track-intents-with-pendingintent","depth":2},{"value":"Common tasks before and after","id":"common-tasks-before-and-after","depth":2},{"value":"Create a user","id":"create-a-user","depth":3},{"value":"Create a transfer","id":"create-a-transfer","depth":3},{"value":"Approve an intent","id":"approve-an-intent","depth":3},{"value":"Behavior differences","id":"behavior-differences","depth":2},{"value":"Next steps","id":"next-steps","depth":2}],"frontmatter":{"seo":{"title":"Migrate from the legacy Java SDK"}},"lastModified":"2026-10-26T19:05:12.528Z","pagePropGetterError":{"message":"","name":""}},"slug":"/products/custody/developer-experience/sdks/migrate-from-legacy-java-sdk","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}