Skip to main content

Get started with the Blueprint SDK — part 1

Overview

This tutorial is part 1 of a two-part introduction to the Hathor Blueprint SDK.

In this first part, you will design a simple swap blueprint before writing code. By the end of this article, you should understand the contract requirements, the public methods, the contract state, the expected actions, and the failure cases that the implementation must handle.

In part 2, you will implement and test the blueprint.

info

The swap blueprint in this tutorial is a learning example. It is intended to show how to reason about blueprint design before implementation. Do not treat it as production-ready swap logic without additional review, testing, and security analysis.

When to use this tutorial

Use this tutorial when you want to:

  • Learn how to translate a nano contract use case into a blueprint design.
  • Understand what information belongs in contract state.
  • Plan the initialize and swap methods before writing Python code.
  • Identify the validation and failure cases that the implementation must enforce.

Prerequisites

Before starting, you should be familiar with:

  • Hathor tokens and token UIDs.
  • Nano contracts and the role of blueprints.
  • The difference between deposits and withdrawals in a nano contract call.

For the broader learning path, see Develop a blueprint.

What you will design

The tutorial uses a simple swap contract as the example.

A swap contract allows a user to exchange one token for another. In this example, each contract instance operates with exactly two tokens, such as token A and token B. The contract holds liquidity for both tokens and authorizes swaps only when the requested deposit and withdrawal match the contract ratio.

For example, a contract may be configured to exchange:

  • 2 units of token A for 1 unit of token B.
  • 1 unit of token B for 2 units of token A.

The goal of this article is not to build a complete decentralized exchange. The goal is to model a small, understandable blueprint that can be implemented and tested in part 2.

Design workflow

You will design the blueprint in this sequence:

  1. Specify requirements.
  2. Model contract interactions.
  3. Model contract state.
  4. Model contract creation.
  5. Model contract execution.
  6. Model execution failures.

Step 1: specify requirements

The swap contracts created from this blueprint must meet the following requirements:

  • Each contract must operate with exactly two tokens, such as token A and token B.
  • A user may swap token A for token B, or token B for token A.
  • Both swap directions must follow the same conversion ratio.
  • The contract must custody both tokens.
  • The contract creator must provide initial liquidity for both tokens during contract creation.
  • The contract does not provide change. Users must request swaps in the exact proportion defined by the contract.

For example, if the contract ratio is 2 token A for 1 token B, a user may deposit 20 token A and withdraw 10 token B. A request to deposit 20 token A and withdraw 9 token B does not match the expected ratio and should fail.

Step 2: model contract interactions

The blueprint needs two public methods.

MethodPurposeWhen it is called
initializeCreates a new swap contract and stores its initial configuration.During contract creation.
swapValidates and authorizes one token swap.During contract execution.

The initialize method is common to blueprints because it defines how a contract instance is created. The swap method is specific to this example because it contains the business logic for exchanging tokens.

This tutorial does not require additional view methods. The information users need is already represented in the contract state: token identifiers, ratio multipliers, swap counter, balances, and blueprint ID.

Step 3: model contract state

Each swap contract needs to store the following attributes:

AttributeType of informationPurpose
token_aToken UIDIdentifies the first token accepted by the contract.
token_bToken UIDIdentifies the second token accepted by the contract.
multiplier_aIntegerDefines the amount of token A used in the conversion ratio.
multiplier_bIntegerDefines the amount of token B used in the conversion ratio.
swaps_counterIntegerCounts successful swaps over the contract lifetime.

The values for token_a, token_b, multiplier_a, and multiplier_b are set when the contract is created. The swaps_counter starts at 0 and increases after each successful swap.

The complete state of a swap contract includes:

  • The blueprint ID.
  • The balances held by the contract.
  • The values of token_a, token_b, multiplier_a, multiplier_b, and swaps_counter.

Step 4: model contract creation

To create a swap contract, a caller must call initialize with:

  • The blueprint ID for the swap blueprint.
  • The initialize method name.
  • The token arguments and ratio multipliers.
  • Initial deposits for both supported tokens.

For example, assume a user wants to create a swap contract with:

  • Token A: <token_A_UID>
  • Token B: <token_B_UID>
  • Ratio: 2 token A for 1 token B
  • Initial liquidity: 200 token A and 100 token B

The contract creation call should conceptually include:

FieldExample value
blueprint_id<swap_blueprint_id>
nc_methodinitialize
nc_argstoken_a=<token_A_UID>, token_b=<token_B_UID>, multiplier_a=2, multiplier_b=1
actionsDeposit 200 token A and deposit 100 token B

The initialize method must validate the business rules for contract creation:

  1. The two token arguments must identify distinct tokens.
  2. The initial deposits must be for exactly the same two tokens configured in the contract.
  3. The ratio multipliers should represent the conversion ratio expected by the contract.

After successful creation, the initial contract state is:

State itemValue
Blueprint ID<swap_blueprint_id>
Balance of <token_A_UID>200
Balance of <token_B_UID>100
token_a<token_A_UID>
token_b<token_B_UID>
multiplier_a2
multiplier_b1
swaps_counter0

Step 5: model contract execution

A user executes a swap by calling the swap method on an existing contract.

The call should include:

  • The contract ID.
  • The swap method name.
  • No additional method arguments.
  • Two actions: one deposit and one withdrawal.

For example, assume a user wants to deposit 20 token A and withdraw 10 token B from the contract created in the previous step.

The call should conceptually include:

FieldExample value
contract_id<swap_contract_id>
nc_methodswap
nc_argsNone
actionsDeposit 20 token A and withdraw 10 token B

The swap method must validate that:

  1. The actions only involve token A and token B.
  2. The actions contain exactly one deposit and one withdrawal.
  3. The deposit and withdrawal amounts match the configured ratio.

If all checks pass, the method increments swaps_counter and returns None. The Hathor engine then applies the approved actions to the contract balance.

After the example swap, the contract state becomes:

State itemValue
Balance of <token_A_UID>220
Balance of <token_B_UID>90
swaps_counter1

Step 6: model execution failures

The swap method should fail when the requested actions do not represent a valid swap.

Failure case 1: deposit or withdrawal without a counterpart

A valid swap must contain exactly one deposit and one withdrawal. The following examples should fail:

  • Deposit 10 token A with no withdrawal.
  • Withdraw 10 token B with no deposit.
  • Deposit 10 token A and deposit 10 token B.
  • Withdraw 20 token A and withdraw 20 token B.
  • Deposit 20 token A, withdraw 10 token A, and deposit 30 token C.

Failure case 2: unsupported token

A valid swap can only involve the two tokens configured during contract creation. The following examples should fail:

  • Deposit 20 token C and withdraw 10 token B.
  • Deposit 10 token C and withdraw 10 token A.
  • Deposit 2 token A and withdraw 1 token C.
  • Deposit 1 token B and withdraw 3 token C.

Failure case 3: invalid conversion ratio

A valid swap must match the ratio configured during contract creation. If the ratio is 2 token A for 1 token B, the following examples should fail:

  • Deposit 20 token A and withdraw 30 token B.
  • Deposit 20 token B and withdraw 20 token A.
note

This tutorial intentionally rejects requests that do not match the expected swap shape, even if the contract would not lose funds. For example, a deposit with no withdrawal still fails because it does not represent the business operation this blueprint is designed to authorize.

Design summary

The swap blueprint design can be summarized as follows:

AreaDesign decision
Public methodsinitialize and swap
State attributestoken_a, token_b, multiplier_a, multiplier_b, swaps_counter
Creation requirementInitial deposits for both supported tokens
Execution requirementExactly one deposit and one withdrawal
Failure handlingReject unsupported tokens, invalid action combinations, and invalid ratios

Next step

You have now designed the swap blueprint. Continue to Get started with the Blueprint SDK — part 2 to implement and test it.