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.
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
initializeandswapmethods 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:
- Specify requirements.
- Model contract interactions.
- Model contract state.
- Model contract creation.
- Model contract execution.
- 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.
| Method | Purpose | When it is called |
|---|---|---|
initialize | Creates a new swap contract and stores its initial configuration. | During contract creation. |
swap | Validates 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:
| Attribute | Type of information | Purpose |
|---|---|---|
token_a | Token UID | Identifies the first token accepted by the contract. |
token_b | Token UID | Identifies the second token accepted by the contract. |
multiplier_a | Integer | Defines the amount of token A used in the conversion ratio. |
multiplier_b | Integer | Defines the amount of token B used in the conversion ratio. |
swaps_counter | Integer | Counts 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, andswaps_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
initializemethod 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:
| Field | Example value |
|---|---|
blueprint_id | <swap_blueprint_id> |
nc_method | initialize |
nc_args | token_a=<token_A_UID>, token_b=<token_B_UID>, multiplier_a=2, multiplier_b=1 |
actions | Deposit 200 token A and deposit 100 token B |
The initialize method must validate the business rules for contract creation:
- The two token arguments must identify distinct tokens.
- The initial deposits must be for exactly the same two tokens configured in the contract.
- The ratio multipliers should represent the conversion ratio expected by the contract.
After successful creation, the initial contract state is:
| State item | Value |
|---|---|
| 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_a | 2 |
multiplier_b | 1 |
swaps_counter | 0 |
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
swapmethod 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:
| Field | Example value |
|---|---|
contract_id | <swap_contract_id> |
nc_method | swap |
nc_args | None |
actions | Deposit 20 token A and withdraw 10 token B |
The swap method must validate that:
- The actions only involve token A and token B.
- The actions contain exactly one deposit and one withdrawal.
- 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 item | Value |
|---|---|
Balance of <token_A_UID> | 220 |
Balance of <token_B_UID> | 90 |
swaps_counter | 1 |
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.
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:
| Area | Design decision |
|---|---|
| Public methods | initialize and swap |
| State attributes | token_a, token_b, multiplier_a, multiplier_b, swaps_counter |
| Creation requirement | Initial deposits for both supported tokens |
| Execution requirement | Exactly one deposit and one withdrawal |
| Failure handling | Reject 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.