> ## 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.

# Algorand

> Derive Algorand addresses and sign transactions using Dynamic embedded wallets

## Overview

Algorand uses the Ed25519 elliptic curve — the same curve as Solana. An Algorand address is the base32-encoded 32-byte public key with a 4-byte checksum appended. No additional hashing is applied to the public key itself.

| Property       | Value                                    |
| -------------- | ---------------------------------------- |
| Curve          | Ed25519                                  |
| Root Wallet    | Solana                                   |
| Address Format | base32(pubkey ‖ checksum\[4]) — 58 chars |
| Hashing        | SHA-512/256 (checksum only)              |
| Serialization  | MessagePack                              |
| Smallest Unit  | microAlgo (1 ALGO = 10^6 microAlgo)      |

## Dependencies

<CodeGroup>
  ```bash npm theme={"system"}
  npm install @noble/hashes bs58
  ```

  ```bash yarn theme={"system"}
  yarn add @noble/hashes bs58
  ```

  ```bash pnpm theme={"system"}
  pnpm add @noble/hashes bs58
  ```

  ```bash bun theme={"system"}
  bun add @noble/hashes bs58
  ```
</CodeGroup>

## Derive Address

Algorand's address is a 32-byte Ed25519 public key encoded in base32, with a 4-byte checksum from SHA-512/256 of the public key:

```typescript theme={"system"}
import { sha512_256 } from "@noble/hashes/sha512.js";
import bs58 from "bs58";

// base32 alphabet (RFC 4648, no padding)
const BASE32_ALPHA = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";

function base32Encode(bytes: Uint8Array): string {
  let result = "";
  let bits = 0;
  let value = 0;
  for (const byte of bytes) {
    value = (value << 8) | byte;
    bits += 8;
    while (bits >= 5) {
      result += BASE32_ALPHA[(value >>> (bits - 5)) & 0x1f];
      bits -= 5;
    }
  }
  if (bits > 0) result += BASE32_ALPHA[(value << (5 - bits)) & 0x1f];
  return result;
}

/**
 * Derive an Algorand address from a Solana address.
 * Algorand address = base32( pubkey || sha512_256(pubkey)[28:32] )
 */
function deriveAlgorandAddress(solanaAddress: string): string {
  const pubkey = bs58.decode(solanaAddress); // 32-byte Ed25519 pubkey
  const checksum = sha512_256(pubkey).slice(28, 32); // last 4 bytes
  const payload = new Uint8Array(36);
  payload.set(pubkey, 0);
  payload.set(checksum, 32);
  return base32Encode(payload);
}
```

## Sign a Message

Sign raw message bytes using the Solana wallet:

```typescript theme={"system"}
import { signMessage } from "@dynamic-labs-sdk/client";
import type { WalletAccount } from "@dynamic-labs-sdk/client";

async function signAlgorandMessage(
  message: string,
  solWallet: WalletAccount
): Promise<string> {
  const messageBytes = new TextEncoder().encode(message);
  const result = await signMessage({
    walletAccount: solWallet,
    message: bytesToHex(messageBytes),
  });
  return result.signature;
}
```

## Verify a Signature

```typescript theme={"system"}
import { ed25519 } from "@noble/curves/ed25519.js";
import bs58 from "bs58";

function verifyAlgorandSignature(
  message: string,
  signature: string,
  solanaAddress: string
): boolean {
  const pubkey = bs58.decode(solanaAddress);
  const messageBytes = new TextEncoder().encode(message);
  const sigBytes = decodeSig(signature); // hex/base64/base58 decode
  return ed25519.verify(sigBytes, messageBytes, pubkey);
}
```

## Check Balance

```typescript theme={"system"}
const ALGOD = "https://testnet-api.algonode.cloud";

async function getAlgorandBalance(address: string): Promise<string> {
  const res = await fetch(`${ALGOD}/v2/accounts/${address}`);
  if (!res.ok) return "0";
  const data = await res.json();
  return (data.amount / 1_000_000).toString();
}
```

## Send a Transaction

Algorand transactions are MessagePack-encoded. This example uses [algosdk](https://www.npmjs.com/package/algosdk) to build and encode the transaction, then signs it with the Dynamic-managed Ed25519 key:

```typescript theme={"system"}
import algosdk from "algosdk";
import { signMessage } from "@dynamic-labs-sdk/client";
import type { WalletAccount } from "@dynamic-labs-sdk/client";
import bs58 from "bs58";

const ALGOD_TOKEN = "";
const ALGOD_SERVER = "https://testnet-api.algonode.cloud";

async function sendAlgorandTransfer(
  to: string,
  amountAlgo: number,
  fromAddress: string,
  solWallet: WalletAccount
): Promise<string> {
  const client = new algosdk.Algodv2(ALGOD_TOKEN, ALGOD_SERVER, "");
  const suggestedParams = await client.getTransactionParams().do();

  const txn = algosdk.makePaymentTxnWithSuggestedParamsFromObject({
    from: fromAddress,
    to,
    amount: Math.round(amountAlgo * 1_000_000),
    suggestedParams,
  });

  // The bytes to sign are "TX" prefix + MessagePack-encoded transaction
  const bytesToSign = txn.bytesToSign();
  const { signature } = await signMessage({
    walletAccount: solWallet,
    message: bytesToHex(bytesToSign),
  });
  const sigBytes = decodeSig(signature);

  const signedTxn = txn.attachSignature(
    bs58.decode(solWallet.address),
    sigBytes
  );
  const result = await client.sendRawTransaction(signedTxn).do();
  return result.txId;
}
```

<Info>
  The Algorand SDK handles the `"TX"` prefix required before signing. If you implement transaction signing without algosdk, prepend the bytes `0x54 0x58` to the transaction bytes before hashing.
</Info>

## React Native

The same derivation and signing logic works in React Native. Replace the `signMessage` import with the React Native client:

```typescript theme={"system"}
// React Native — use the client SDK directly
const wallet = dynamicClient.wallets.userWallets.find(w => w.chain === "SOL")!;
const { signedMessage } = await dynamicClient.wallets.signMessage({
  wallet,
  message: bytesToHex(bytesToSign),
});
```

See the [React Native Algorand guide](/react-native/chains/tier-2-chains/algorand) for a full walkthrough.
