Get-методы
Прежде чем продолжить, рекомендуется ознакомиться с основами языка программирования FunC на блокчейне TON. Это поможет лучше понять представленную ниже информацию.
Введение
Get-методы — это специальные функции, предназначенные для получения конкретных данных из состояния смарт-контракта. Их выполнение происходит вне блокчейна и не требует комиссии.
Эти функции встречаются во многих смарт-контрактах. Например, стандартный смарт-контракт кошелька содержит несколько get-методов: seqno(), get_subwallet_id() и get_public_key(). Они позволяют получать данные о кошельке из самого контракта, SDK и API.
Шаблоны проектирования для get-методов
Базовые шаблоны
-
Получение отдельных данных. Данный шаблон представляет собой набор методов, которые позволяют получить в качестве результата вызова отдельные параметры из состояния контракта. Данные методы не содержат аргументов и возвращают только одно значение.
Например:
int get_balance() method_id {
return get_data().begin_parse().preload_uint(64);
} -
Получение агрегированных данных. Ещё один распространённый шаблон - набор методов, позволяющих извлечь сразу массив данных из состояния контракта в рамках одиночного вызова. Это может быть удобно для случаев, когда для какой-то операции необходимо несколько параметров. Такие методы применяются, например, в контрактах Jetton и NFT.
Например:
(int, slice, slice, cell) get_wallet_data() method_id {
return load_data();
}
Продвинутые шаблоны
-
Получение вычисляемых данных. В некоторых случаях искомые данные не хранятся в текущем состоянии контракта, однако могут быть вычислены, если в метод будут переданы дополнительные аргументы для расчета.
Например:
slice get_wallet_address(slice owner_address) method_id {
(int total_supply, slice admin_address, cell content, cell jetton_wallet_code) = load_data();
return calculate_user_jetton_wallet_address(owner_address, my_address(), jetton_wallet_code);
} -
Получение данных с учетом условий. Иногда значения, которые нужно получить, зависят от каких-либо параметров, к примеру, от текущего времени.
Например:
(int) get_ready_to_be_used() method_id {
int ready? = now() >= 1686459600;
return ready?;
}
Наиболее распространенные get-методы
Стандартные кошельки
seqno()
int seqno() method_id {
return get_data().begin_parse().preload_uint(32);
}
Возвращает порядковый номер транзакции в оп ределённом кошельке. Этот метод в основном используется для защиты от повторных отправок.
get_subwallet_id()
int get_subwallet_id() method_id {
return get_data().begin_parse().skip_bits(32).preload_uint(32);
}
get_public_key()
int get_public_key() method_id {
var cs = get_data().begin_parse().skip_bits(64);
return cs.preload_uint(256);
}
Получает публичный ключ, связанный с кошельком.
Жетоны
get_wallet_data()
(int, slice, slice, cell) get_wallet_data() method_id {
return load_data();
}
Этот метод возвращает полный набор данных, связанных с кошельком Jetton:
- (int) balance
- (slice) owner_address
- (slice) jetton_master_address
- (cell) jetton_wallet_code
get_jetton_data()
(int, int, slice, cell, cell) get_jetton_data() method_id {
(int total_supply, slice admin_address, cell content, cell jetton_wallet_code) = load_data();
return (total_supply, -1, admin_address, content, jetton_wallet_code);
}
Возвращает данные мастер-контракта Jetton, включая общий объём, адрес администратора, содержимое жетона и код кошелька.
get_wallet_address(slice owner_address)
slice get_wallet_address(slice owner_address) method_id {
(int total_supply, slice admin_address, cell content, cell jetton_wallet_code) = load_data();
return calculate_user_jetton_wallet_address(owner_address, my_address(), jetton_wallet_code);
}
На осно ве адреса владельца этот метод вычисляет и возвращает адрес его кошелька Jetton.
NFT
get_nft_data()
(int, int, slice, slice, cell) get_nft_data() method_id {
(int init?, int index, slice collection_address, slice owner_address, cell content) = load_data();
return (init?, index, collection_address, owner_address, content);
}
Возвращает данные, связанные с невзаимозаменяемым токеном, включая информацию о том, был ли он инициал изирован, индекс в коллекции, адрес коллекции, адрес владельца и индивидуальное содержимое.
get_collection_data()
(int, cell, slice) get_collection_data() method_id {
var (owner_address, next_item_index, content, _, _) = load_data();
slice cs = content.begin_parse();
return (next_item_index, cs~load_ref(), owner_address);
}
Возвращает данные о коллекции NFT, включая индекс следующего элемента для минта, содержимое коллекции и адрес владельца.
get_nft_address_by_index(int index)
slice get_nft_address_by_index(int index) method_id {
var (_, _, _, nft_item_code, _) = load_data();
cell state_init = calculate_nft_item_state_init(index, nft_item_code);
return calculate_nft_item_address(workchain(), state_init);
}
С учетом индекса, этот метод вычисляет и возвращает адрес соответствующего контракта NFT-элемента этой коллекции.
royalty_params()
(int, int, slice) royalty_params() method_id {
var (_, _, _, _, royalty) = load_data();
slice rs = royalty.begin_parse();
return (rs~load_uint(16), rs~load_uint(16), rs~load_msg_addr());
}
Получает параметры роялти для NFT. Эти параметры включают процент роялти, который выплачивается первоначальному создателю при продаже NFT.
get_nft_content(int index, cell individual_nft_content)
cell get_nft_content(int index, cell individual_nft_content) method_id {
var (_, _, content, _, _) = load_data();
slice cs = content.begin_parse();
cs~load_ref();
slice common_content = cs~load_ref().begin_parse();
return (begin_cell()
.store_uint(1, 8) ;; offchain tag
.store_slice(common_content)
.store_ref(individual_nft_content)
.end_cell());
}
С учетом индекса и индивидуального содержимого NFT, этот метод получает и возвращает объединённое общее и индивидуальное содержимое NFT.
Как работать с get-методами
Поиск get-методов на популярных обозревателях
Tonviewer
Вы можете вызвать get-методы в нижней части страницы во вкладке "Methods"
Ton.cx
Вы можете вызвать get-методы во вкладке "Get methods"
Вызов get-методов из кода
В примерах ниже мы будем использовать библиотеки и инструменты JavaScript:
Представим, что у нас есть контракт со следующим get-методом:
(int) get_total() method_id {
return get_data().begin_parse().preload_uint(32); ;; load and return the 32-bit number from the data
}
Этот метод возвращает значение в виде числа из данных контракта.
Приведенный ниже фрагмент кода позволяет вызвать этот get-метод в контракте, развёрнутом по известному адресу:
import { TonClient } from '@ton/ton';
import { Address } from '@ton/core';
async function main() {
// Create Client
const client = new TonClient({
endpoint: 'https://toncenter.com/api/v2/jsonRPC',
});
// Call get method
const result = await client.runMethod(
Address.parse('EQD4eA1SdQOivBbTczzElFmfiKu4SXNL4S29TReQwzzr_70k'),
'get_total'
);
const total = result.stack.readNumber();
console.log('Total:', total);
}
main();
Этот код выдаст результат Total: 123. Число может быть другим, это просто пример.