Skip to main content

Documentation Index

Fetch the complete documentation index at: https://www.dynamic.xyz/docs/llms.txt

Use this file to discover all available pages before exploring further.

Overview

DynamicSvmWalletClient::signMessage signs raw bytes with Ed25519 and returns a base58-encoded 64-byte signature. The signature is over the raw message bytes — no Solana-specific message envelope is applied.

Prerequisites

Basic Message Signing

import java.nio.charset.StandardCharsets;
import java.util.List;
import xyz.dynamic.waas.ServerKeyShare;
import xyz.dynamic.waas.core.types.WalletProperties;
import xyz.dynamic.waas.opts.SignMessageOpts;
import xyz.dynamic.waas.svm.DynamicSvmWalletClient;

// Load the metadata + shares you persisted at creation time.
WalletProperties walletProperties = WalletProperties.fromJson(
    redis.get("wallet:" + accountAddress)
);
List<ServerKeyShare> externalServerKeyShares = ServerKeyShare.fromJsonList(
    vault.read("wallet:" + accountAddress + "/shares")
);

String signatureB58 = client.signMessage(SignMessageOpts.builder()
    .message("Hello, World!".getBytes(StandardCharsets.UTF_8))
    .walletProperties(walletProperties)
    .externalServerKeyShares(externalServerKeyShares)
    .build()
).join();

System.out.println("Signature: " + signatureB58);

Verifying the signer locally

Verify the signature against the account address (a base58-encoded Ed25519 public key) with the JDK’s built-in Signature API plus any base58 codec — here using sava-core:
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.X509EncodedKeySpec;
import software.sava.core.encoding.Base58;

byte[] pubkeyBytes = Base58.decode(walletProperties.accountAddress()); // 32 bytes
byte[] sigBytes    = Base58.decode(signatureB58);                      // 64 bytes

// SubjectPublicKeyInfo prefix for Ed25519 raw 32-byte pubkey:
byte[] prefix = new byte[] {
    0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x70, 0x03, 0x21, 0x00
};
byte[] spki = new byte[prefix.length + pubkeyBytes.length];
System.arraycopy(prefix, 0, spki, 0, prefix.length);
System.arraycopy(pubkeyBytes, 0, spki, prefix.length, pubkeyBytes.length);

PublicKey publicKey = KeyFactory.getInstance("Ed25519")
    .generatePublic(new X509EncodedKeySpec(spki));

Signature verifier = Signature.getInstance("Ed25519");
verifier.initVerify(publicKey);
verifier.update("Hello, World!".getBytes(StandardCharsets.UTF_8));

assert verifier.verify(sigBytes) : "signature does not verify";

Use case: off-chain auth

Common pattern for nonce-based wallet auth:
String nonce   = java.util.UUID.randomUUID().toString();
String message = "Sign this nonce to authenticate: " + nonce;

String signatureB58 = client.signMessage(SignMessageOpts.builder()
    .message(message.getBytes(StandardCharsets.UTF_8))
    .walletProperties(walletProperties)
    .externalServerKeyShares(externalServerKeyShares)
    .build()
).join();

Next Steps