Mavryk (a fork of Tezos) uses the Ed25519 elliptic curve. Addresses are derived with Blake2b-160 hashing and encoded using b58cencode from @mavrykdynamics/webmavryk-utils. Transactions are built and submitted using MavrykToolkit from @mavrykdynamics/webmavryk.This guide covers Ed25519 (mv1) addresses only. Mavryk also supports Secp256k1 (mv2), P-256 (mv3), and BLS12-381 (mv4); Dynamic’s embedded wallet flow here assumes Ed25519 keys.
Use MavrykToolkit with a custom signer that routes signing through Dynamic’s signMessage. The toolkit handles forging, watermarking, and injection automatically.
import { signMessage } from "@dynamic-labs-sdk/client";import type { WalletAccount } from "@dynamic-labs-sdk/client";import { hash } from "@stablelib/blake2b";import { hex2buf, buf2hex, mergebuf, b58cencode, prefix, Prefix,} from "@mavrykdynamics/webmavryk-utils";import { MavrykToolkit } from "@mavrykdynamics/webmavryk";import bs58 from "bs58";const MAVRYK_RPC = "https://rpc.mavryk.network";class DynamicMavrykSigner { constructor( private pubkeyBytes: Uint8Array, private wallet: WalletAccount, ) {} async publicKey() { return b58cencode(this.pubkeyBytes, prefix[Prefix.EDPK]); } async publicKeyHash() { return b58cencode(hash(this.pubkeyBytes, 20), prefix[Prefix.MV1]); } async secretKey(): Promise<string | undefined> { return undefined; } async sign(bytes: string, watermark?: Uint8Array) { let buf = hex2buf(bytes); if (watermark) buf = mergebuf(watermark, buf); // Mavryk requires Blake2b-256 pre-hash before signing const digest = hash(buf, 32); const { signature } = await signMessage({ walletAccount: this.wallet, message: buf2hex(digest), }); // Dynamic returns the signature as base58; decode before encoding const sigBytes = bs58.decode(signature); return { bytes, sig: b58cencode(sigBytes, prefix[Prefix.SIG]), prefixSig: b58cencode(sigBytes, prefix[Prefix.EDSIG]), sbytes: bytes + buf2hex(sigBytes), }; }}async function sendMavrykTransfer( to: string, amount: number, wallet: WalletAccount,): Promise<string> { const pubkeyBytes = bs58.decode(wallet.address); const signer = new DynamicMavrykSigner(pubkeyBytes, wallet); const toolkit = new MavrykToolkit(MAVRYK_RPC); toolkit.setSignerProvider(signer); const op = await toolkit.contract.transfer({ to, amount }); await op.confirmation(1); return op.hash;}
MavrykToolkit handles operation forging, watermarking (0x03), and injection. The custom signer applies Blake2b-256 pre-hashing before passing the digest to Dynamic’s signMessage.
Last modified on September 21, 2026
Assistant
Responses are generated using AI and may contain mistakes.