Skip to content

Memo and key utilities

Use this guide when your application needs to work directly with Blurt keys, signatures or encrypted transfer memos.

For broadcast authority choices, read Accounts and authorities and Broadcast safely. For exact API signatures, use the API reference.

Key classes

@beblurt/dblurt exports the protocol key and signature classes used by transaction signing and memo encryption:

ts
import { PrivateKey, PublicKey, Signature } from '@beblurt/dblurt';

const privateKey = PrivateKey.fromString(process.env.BLURT_POSTING_KEY ?? '');
const publicKey = privateKey.createPublic();

console.log(publicKey.toString());

Use the key role that matches the workflow:

Key roleTypical use
postingcontent, votes and social custom JSON
activetransfers, vesting, savings, proposals and other account/fund operations
ownerrecovery and ownership changes
memoencrypted transfer memos

A memo key is not a broadcast authority. It is used for memo encryption/decryption.

Plain and encrypted memos

Layer 1 transfer operations carry a memo string. Applications decide whether the memo is plain text or encrypted.

encodeMemo() follows the Blurt convention that only memos beginning with # are encrypted. Plain memos are returned unchanged.

ts
import { encodeMemo } from '@beblurt/dblurt';

const encrypted = encodeMemo(
    '#invoice 1234',
    senderPrivateMemoKey,
    receiverPublicMemoKey
);

decodeMemo() decrypts memos beginning with #. Plain memos are returned unchanged.

ts
import { decodeMemo } from '@beblurt/dblurt';

const plain = decodeMemo(encrypted, receiverPrivateMemoKey);

Legacy memo security limitations

Encrypted memos use the legacy Blurt/Graphene-compatible memo format. Keep compatibility expectations separate from modern encryption guarantees:

  • memo encryption is not a replacement for transaction authorization;
  • memo keys encrypt and decrypt, while active/posting/owner keys authorize operations;
  • applications should treat malformed encrypted memos as untrusted input and handle decode failures explicitly;
  • do not build new high-security messaging protocols on top of the legacy memo format without a separate authenticated design.

decodeMemo() returns plain memos unchanged, but encrypted memos beginning with # must decode successfully before an application treats the result as trusted plaintext.

Transfer workflow

When broadcasting a transfer with an encrypted memo:

  1. Resolve the recipient's public memo key from account data.
  2. Encrypt the memo locally with encodeMemo().
  3. Put the encrypted string in the transfer operation's memo field.
  4. Sign the transfer with the required active authority.
ts
const [receiver] = await client.condenser.getAccounts(['bob']);
const memo = encodeMemo('#payment for invoice 1234', senderMemoKey, receiver.memo_key);

await client.broadcast.transfer({
    from: 'alice',
    to: 'bob',
    amount: '1.000 BLURT',
    memo
}, activeKey);

Verification notes

  • Store private keys in application-controlled secret storage or wallet-controlled flows.
  • Do not log private keys.
  • Do not assume a transfer memo is encrypted unless it starts with # and decodes successfully.
  • Keep memo encryption separate from broadcast signing: memo keys encrypt/decrypt; active keys authorize transfers.

API details