Transactions

Official Tessellation documentation on transaction types.


Single $DAG Transaction

Note

Amount and fee are 8-decimal integers (dDAG), i.e. 1 DAG equals 100000000 dDAG.

from pypergraph.dag_account import DagAccount
import asyncio

async def execute_transfer():
    # Initialize the account and log in using a seed phrase.
    account = DagAccount()
    account.login_with_seed_phrase("abandon abandon ...")

    # Initiate a transfer which returns a pending transaction.
    pending_transaction = await account.transfer(
        to_address="DAG1...",
        amount=100000000,  # 1 DAG = 10^8 units
        fee=200000
    )
    print(f"Transaction ID: {pending_transaction.hash}")

# Execute the async transfer function.
asyncio.run(execute_transfer())
Transaction Creation Lifecycle
# Transaction preparation: generate and sign a transaction.
tx, tx_hash = await account.generate_signed_transaction(
    to_address="DAG1...",
    amount=100000000,
    fee=20000,
    last_ref=await account.network.get_address_last_accepted_transaction_ref(account.address)
)

# Network submission: post the transaction to the network.
await account.network.post_transaction(tx)

Batch $DAG Transactions

Note

Amount and fee are 8-decimal integers (dDAG), i.e. 1 DAG equals 100000000 dDAG.

async def batch_transfers():
    # Log in using a seed phrase.
    account = DagAccount().login_with_seed_phrase("abandon abandon ...")

    # Define multiple transfers in a batch.
    transfers = [
        {"to_address": "DAG1...", "amount": 100000000},
        {"to_address": "DAG2...", "amount": 50000000, "fee": 200000}
    ]
    # Execute the batch transfer.
    tx_hashes = await account.transfer_batch(transfers=transfers)

Metagraph Token

Note

Amount and fee are 8-decimal integers (dDAG), i.e. 1 token equals 100000000 units.

from pypergraph.dag_account import MetagraphTokenClient
import asyncio

async def metagraph_transfer():
    # Log in using a seed phrase.
    account = DagAccount().login_with_seed_phrase("abandon ...")

    # Create a Metagraph token client with custom node configurations.
    metagraph_client = MetagraphTokenClient(
        account=account,
        metagraph_id="DAG7...",
        l0_host="http://custom-l0-node:9100",
        cl1_host="http://custom-cl1-node:9200"
    )

    # Initiate a metagraph transfer.
    tx_hash = await metagraph_client.transfer(
        to_address="DAG9...",
        amount=100000000,
        fee=0  # Metagraph-specific fee rules
    )
Alternative Metagraph Client Creation
# Alternative method to create a Metagraph token client.
metagraph_client = account.create_metagraph_token_client(
    metagraph_id="DAG7...",
    # Additional configuration parameters as needed.
    dl1_host="http://custom-cl1-node:9200"
)

Metagraph Data

Transaction values, serialization and encoding should match what is expected by the Metagraph.

from pypergraph.dag_keystore import KeyStore
import asyncio

async def submit_metagraph_data():
    # Log in using a seed phrase.
    account = DagAccount().login_with_seed_phrase("abandon ...")

    # Create a Metagraph token client (alternative method).
    metagraph_client = account.create_metagraph_token_client(
        metagraph_id="DAG7...",
        # Additional configuration parameters as needed.
        dl1_host="http://custom-dl1-node:9300"
    )

    # Define the payload for the Metagraph data submission.
    payload = {
        "CreatePoll": {
            "name": "consensus_vote",
            "owner": account.address,
            "pollOptions": ["approve", "reject"],
            "startSnapshotOrdinal": 1000,
            "endSnapshotOrdinal": 100000
        }
    }

    # Sign the payload.
    signature, data_hash = KeyStore().data_sign(
        private_key=account.private_key,
        msg=payload
    )

    # Post the signed data to the network.
    response = await metagraph_client.network.post_data({
        "value": payload,
        "proofs": [
            {
                "id": account.public_key[2:],  # Compressed public key (remove "04" prefix)
                "signature": signature
            }
        ]
    })
Data Signing Configuration

Serialization Options

  • prefix=True (default) or False to exclude the default data preamble.

  • encoding=None (default) or e.g., "base64" or a custom encoding function.

def base64_serializer(data: dict) -> str:
    import base64, json
    return base64.b64encode(
        json.dumps(data, separators=(",", ":")).encode()
    ).decode()

# Sign the payload with custom serialization settings.
signature, data_hash = KeyStore().data_sign(
    private_key=account.private_key,
    msg=payload,
    prefix=False,
    encoding=base64_serializer
)

Check Pending Transaction

import asyncio

async def accepted(tx: PendingTransaction) -> bool:
    """
    Wait until the given transaction is accepted in a checkpoint.

    Args:
        tx (PendingTransaction): A PendingTransaction instance.

    Returns:
        bool: True when the transaction is accepted.
    """
    while not await account.wait_for_checkpoint_accepted(tx.hash):
        await asyncio.sleep(6)  # Prevent busy-waiting
    return True

async def main():
    # Initiate a transfer which returns a pending transaction.
    pending_transaction = await account.transfer(
        to_address="DAG1...",
        amount=100000000,  # 1 DAG = 10^8 units
        fee=200000
    )

    # Check if the transaction has been accepted.
    if await accepted(pending_transaction):
        print("Accepted:", pending_transaction.hash)

# Execute the async main function.
asyncio.run(main())