Anchor
Anchor Escrow

Anchor Escrow

75 Graduates

Anchor Escrow Challenge

Ескроу

Ескроу — це потужний фінансовий інструмент, який забезпечує безпечний обмін токенами між двома сторонами.

Уявіть це як цифрову банківську скриньку, де один користувач може заблокувати Токен А, очікуючи, поки інший користувач внесе Токен Б перед завершенням обміну.

Це створює середовище без довіри, де жодній стороні не потрібно турбуватися про те, що інша відмовиться від угоди.

У цьому завданні ми реалізуємо цю концепцію через три прості, але потужні інструкції:

  • Make: Мейкер (перший користувач) визначає умови угоди та вносить узгоджену кількість Токена А у захищене сховище. Це схоже на розміщення вашого предмета в банківській скриньці та встановлення умов обміну.

  • Take: Тейкер (другий користувач) приймає пропозицію, переказуючи обіцяну кількість Токена Б мейкеру, і натомість отримує заблокований Токен А. Це момент, коли обидві сторони виконують свою частину угоди.

  • Refund: Якщо мейкер змінює своє рішення або не знаходиться відповідний тейкер, він може скасувати пропозицію та повернути свій Токен А. Це схоже на повернення вашого предмета з банківської скриньки, якщо угода зривається.

Примітка: Якщо ви не знайомі з Anchor, вам варто почати з читання Anchor для початківців, щоб ознайомитися з основними концепціями, які ми будемо використовувати в цій програмі.

Встановлення

Почнімо зі створення нового робочого простору Anchor:

anchor init blueshift_anchor_escrow
cd blueshift_anchor_escrow

Далі ми продовжуємо, активуючи init-if-needed у крейті anchor-lang та додаючи крейт anchor-spl:

cargo add anchor-lang --features init-if-needed
cargo add anchor-spl

Оскільки ми використовуємо anchor-spl, нам також потрібно оновити файл programs/blueshift_anchor_escrow/Cargo.toml, щоб включити anchor-spl/idl-build у функцію idl-build.

Відкрийте Cargo.toml і ви побачите існуючий рядок idl-build, який виглядає так:

toml
idl-build = ["anchor-lang/idl-build"]

Змініть його, щоб додати також anchor-spl/idl-build:

toml
idl-build = ["anchor-lang/idl-build", "anchor-spl/idl-build"]

Тепер ви можете відкрити новостворену папку і готові почати кодування!

Template

Цього разу, оскільки програма досить складна, ми розділимо її на невеликі, сфокусовані модулі замість того, щоб все запихати у lib.rs.

Структура папок буде приблизно такою:

text
src
├── instructions
│       ├── make.rs
│       ├── mod.rs
│       ├── refund.rs
│       └── take.rs
├── errors.rs
├── lib.rs
└── state.rs

При цьому lib.rs буде виглядати приблизно так:

rust
use anchor_lang::prelude::*;

mod state;
mod errors;
mod instructions;
use instructions::*;

declare_id!("22222222222222222222222222222222222222222222");

#[program]
pub mod blueshift_anchor_escrow {
    use super::*;

    #[instruction(discriminator = 0)]
    pub fn make(ctx: Context<Make>, seed: u64, receive: u64, amount: u64) -> Result<()> {
        //...
    }

    #[instruction(discriminator = 1)]
    pub fn take(ctx: Context<Take>) -> Result<()> {
        //...
    }

    #[instruction(discriminator = 2)]
    pub fn refund(ctx: Context<Refund>) -> Result<()> {
        //...
    }
}

Як бачите, ми реалізували власний дискримінатор для інструкцій. Тому переконайтеся, що використовуєте версію anchor 0.31.0 або новішу.

State

Ми перейдемо до state.rs, де зберігаються всі дані для нашого Escrow. Для цього ми надамо йому власний дискримінатор і обгорнемо структуру в макрос #[account] ось так:

rust
use anchor_lang::prelude::*;

#[derive(InitSpace)]
#[account(discriminator = 1)]
pub struct Escrow {
    pub seed: u64,
    pub maker: Pubkey,
    pub mint_a: Pubkey,
    pub mint_b: Pubkey,
    pub receive: u64,
    pub bump: u8,
}

Що робить кожне поле:

  • seed: Випадкове число, яке використовується під час виведення сіда, щоб один мейкер міг відкрити кілька ескроу з однією і тією ж парою токенів; зберігається в блокчейні, щоб ми завжди могли повторно вивести PDA.

  • maker: Гаманець, який створив ескроу; потрібен для повернення коштів і отримання платежу.

  • mint_a і mint_b: Адреси SPL-мінтів для сторін "віддати" та "отримати" свопу.

  • receive: Скільки токенів B хоче отримати мейкер. (Баланс сховища сам показує, скільки токенів A було внесено, тому ми це не зберігаємо.)

  • bump: Кешований байт бампу; виведення його на льоту коштує обчислювальних ресурсів, тому ми зберігаємо його один раз.

Ми могли б додати більше інформації, але додаткові байти означають додаткову оренду. Зберігання лише необхідного мінімуму робить депозити дешевими, при цьому дозволяючи програмі застосовувати всі потрібні правила.

Ми завершуємо додаванням макросу #[derive(InitSpace)], щоб не розраховувати оренду цієї структури вручну.

Errors

Тепер ми можемо перейти до файлу errors.rs, де ми додамо деякі помилки, які будемо використовувати пізніше, ось так:

rust
use anchor_lang::prelude::*;

#[error_code]
pub enum EscrowError {
    #[msg("Invalid amount")]
    InvalidAmount,
    #[msg("Invalid maker")]
    InvalidMaker,
    #[msg("Invalid mint a")]
    InvalidMintA,
    #[msg("Invalid mint b")]
    InvalidMintB,
}

Кожен enum відповідає чіткому, зрозумілому для людини повідомленню, яке Anchor показуватиме щоразу, коли обмеження або require!() не виконуються.

Next PageСтворити
АБО ПЕРЕЙТИ ДО ЗАВДАННЯ
Готові прийняти завдання?
Blueshift © 2025Commit: e573eab