智能合约 API 函数
原文:https://docs.elrond.com/developers/developer-reference/elrond-wasm-api-functions
Rust 框架提供了Elrond VM API 函数和账户级内置函数的包装器。它们被分成多个模块,按类别分组:
- BlockchainApi:提供一般的区块链信息,范围从帐户余额、NFT 元数据/角色到关于当前和先前块的信息(nonce、epoch 等)。)
- CallValueApi:在可支付端点中使用,提供关于作为支付接收的代币的信息(代币类型、nonce、数量)
- CryptoApi:提供对哈希和签名检查等加密功能的支持
- SendApi:处理所有类型的帐户转移和智能合约呼叫/部署/升级,以及对 ESDT 本地内置功能的支持
api 的源代码可以在这里找到:https://github . com/elrond network/elrond-wasm-RS/tree/master/elrond-wasm/src/API
区块链 API
这个 API 可以通过self.blockchain()
访问。可用功能:
get _ sc _ address
get_sc_address() -> ManagedAddress
返回智能合约自己的地址。
获取 _ 所有者 _ 地址
get_owner_address() -> ManagedAddress
返回所有者的地址。
查 _ 来电 _ 是 _ 车主
check_caller_is_owner()
如果调用方不是所有者,则终止执行并发出错误信号。
使用#[only_owner]
端点注释,而不是直接调用这个函数。
获取 _ 分片 _ 地址
get_shard_of_address(address: &ManagedAddress) -> u32
返回作为参数传递的地址碎片。
是 _ 智能 _ 合约
is_smart_contract(address: &ManagedAddress) -> bool
如果作为参数传递的地址是智能合约地址,则返回true
,对于简单帐户,返回false
。
get _ caller
get_caller() -> ManagedAddress
返回当前调用方。
请记住,对于 SC 查询,该函数将返回 SC 自己的地址,因此使用该 API 函数的视图函数不会有预期的行为。
获取 _ 平衡
get_balance(address: &ManagedAddress) -> BigUint
返回给定地址的 EGLD 余额。
这只适用于与智能合约位于同一个碎片中的地址。
get _ sc _ balance
get_sc_balance(token: &EgldOrEsdtTokenIdentifier, nonce: u64) -> BigUint
返回智能合约的 EGLD/ESDT/NFT 余额。
对于可替换的 ESDT,nonce 应该为 0。要获得 EGLD 平衡,您可以简单地将EgldOrEsdtTokenIdentifier::egld()
作为参数传递。
get _ tx _ hash
get_tx_hash() -> ManagedByteArray<Self::Api, 32>
返回当前的发送哈希。
在异步调用的情况下,原始调用和相关回调中的 tx 散列是相同的。
get _ gas _ left
get_gas_left() - > u64
返回调用时剩余的气体。
这对于昂贵的操作很有用,比如遍历存储中的一组用户并发送奖励。
用完燃气的智能合约调用将恢复所有操作,因此该函数可用于在用完燃气之前返回,保存一个检查点,并在第二次调用时继续。
获取 _ 块 _ 时间戳
get_block_timestamp() -> u64
get _ block _ nonce
get_block_nonce() -> u64
get _ block _ round
get_block_round() -> u64
get _ block _ epoch
get_block_epoch() -> u64
这些功能主要用于设置截止日期,所以它们被组合在一起。
获取 _ 区块 _ 随机 _ 种子
get_block_random_seed() -> ManagedByteArray<Self::Api, 48>
返回块随机种子,可用于生成随机数。
这对于当前块中的所有调用都是相同的,因此可以通过某人在该轮开始时调用此调用,然后调用您的合约来预测。
get _ prev _ block _ timestamp
get_prev_block_timestamp() -> u64
get _ prev _ block _ nonce
get_prev_block_nonce() -> u64
get _ prev _ block _ round
get_prev_block_round() -> u64
get _ prev _ block _ epoch
get_prev_block_epoch() -> u64
get _ prev _ block _ random _ seed
get_prev_block_random_seed() -> ManagedByteArray<Self::Api, 48>
与上面的函数相同,但用于前一个块而不是当前块。
获取 _ 当前 _esdt_nft_nonce
get_current_esdt_nft_nonce(address: &ManagedAddress, token_id: &TokenIdentifier) -> u64
获取 SFT/NFT 的最后一个随机数。Nonces 在每次 ESDTNFTCreate 操作后递增。
这仅适用于设置了 ESDTNFTCreateRole 的帐户,并且仅适用于与智能合约位于同一分片中的帐户。
该函数通常与self.blockchain().get_sc_address()
一起用于创建 SFT/NFT 的智能合约。
get _ esdt _ balance
get_esdt_balance(address: &ManagedAddress, token_id: &TokenIdentifier, nonce: u64) -> BigUint
获取指定地址的 ESDT/SFT/NFT 余额。
这只适用于与智能合约位于同一个碎片中的地址。
对于可替换的 ESDT,nonce 应该为 0。对于 EGLD 平衡,使用get_balance
代替。
get _ esdt _ token _ data
get_esdt_token_data(address: &ManagedAddress, token_id: &TokenIdentifier, nonce: u64) -> EsdtTokenData<Self::Api>
获取由指定地址拥有的特定代币类型的 ESDT 代币属性。
EsdtTokenData
有以下格式:
pub struct EsdtTokenData<M: ManagedTypeApi> {
pub token_type: EsdtTokenType,
pub amount: BigUint<M>,
pub frozen: bool,
pub hash: ManagedBuffer<M>,
pub name: ManagedBuffer<M>,
pub attributes: ManagedBuffer<M>,
pub creator: ManagedAddress<M>,
pub royalties: BigUint<M>,
pub uris: ManagedVec<M, ManagedBuffer<M>>,
}
token_type
是一个枚举,可以具有下列值之一:
pub enum EsdtTokenType {
Fungible,
NonFungible,
SemiFungible,
Meta,
Invalid,
}
您将只收到代币类型的基本区别,即只有Fungible
和NonFungible
(智能合约无法区分不可替代、半可替代和元代币)。
amount
是账户当前拥有的余额。
frozen
为布尔值,表示账户是否被冻结。
hash
是 NFT 的杂凑。一般来说,这将是attributes
的散列,但是这不是强制的。此外,哈希长度也不固定。
name
是 NFT 的名称,通常在前端应用程序中用作显示名称。
attributes
可以包含任何用户自定义的数据。如果您知道格式,您可以使用EsdtTokenData::decode_attributes
方法来反序列化它们。
creator
是创作者的地址。
0 到 10,000 之间的一个数字,表示创作者获得的任何销售价格的百分比。这是用在 ESDT NFT 市场,但没有以任何其他方式强制执行。(这些百分比的工作方式是 5,444 将是 54.44%,您将计算它:价格* 5,444 / 10,000。该约定用于授予一些额外的精度)
uris
列出 URIs 给的一个图像/音频/视频,它代表给定的 NFT。
这只适用于与智能合约位于同一个碎片中的地址。
大多数情况下,该函数与作为地址的self.blockchain().get_sc_address()
一起使用,以获取智能合约拥有的代币的属性,或者在当前执行的调用中被转移到智能合约的代币的属性。
get _ esdt _ local _ roles
get_esdt_local_roles(token_id: &TokenIdentifier) -> EsdtLocalRoleFlags
以位标志形式获取为智能合约设置的 ESDTLocalRoles。返回的类型包含检查角色是否存在以及迭代所有角色的方法。
这是通过简单地读取受保护的存储器来完成的,但是这是一个使用方便的函数。
调用值 API
这个 API 可以通过self.call_value()
访问。替代方法是使用#[payment]
注释,但是我们不再推荐它们。他们有制造混乱的历史,尤其是对新用户。
可用功能:
egld _ value
egld_value() -> BigUint
返回当前交易中传输的 EGLD 的数量。将为 ESDT 转账返回 0。
所有 _ esdt _ 转账
all_esdt_transfers() -> ManagedVec<EsdtTokenPayment<Self::Api>>
返回所有 ESDT 转移。当您期望可变的传输次数时,这很有用。
将付款返回到结构的ManagedVec
中,该结构包含代币类型、代币 ID、代币 nonce 和被转移的金额:
pub struct EsdtTokenPayment<M: ManagedTypeApi> {
pub token_identifier: TokenIdentifier<M>,
pub token_nonce: u64,
pub amount: BigUint<M>,
}
多 _esdt
multi_esdt<const N: usize>() -> [EsdtTokenPayment<Self::Api>; N]
以数组形式返回固定数量的 ESDT 传输。如果 ESDT 传送的数量与N
不同,将发出错误信号。
例如,如果您总是期望在您的端点中正好有 3 笔付款,您可以这样使用此函数:
let [payment_a, payment_b, payment_c] = self.call_value().multi_esdt();
single _ esdt
single_esdt() -> EsdtTokenPayment<Self::Api>
如果恰好收到一笔 ESDT 代币,则返回收到的代币付款。在多次传送或不传送的情况下将发出错误信号。
单一 _ 可替代 _esdt
single_fungible_esdt(&self) -> (TokenIdentifier, BigUint)
类似于上面的功能,还强制支付为可替换的 ESDT。
egld _ or _ single _ 可替换 _esdt
egld_or_single_fungible_esdt(&self) -> (EgldOrEsdtTokenIdentifier<Self::Api>, BigUint)
与上述功能相同,但也允许接收 EGLD。
egld _ or _ single _ esdt
egld_or_single_esdt() -> EgldOrEsdtTokenPayment<Self::Api>
允许接收 EGLD 或任何单个 ESDT 代币。
加密 API
这个 API 可以通过self.crypto()
访问。它提供散列函数和签名验证。因为这些函数是众所周知的,并且有自己的文档,所以我们在这一节就不详细介绍了。
哈希函数:
sha256
sha256(data: &ManagedBuffer) -> ManagedByteArray<Self::Api, 32>
keccak 256
keccak256(data: &ManagedBuffer) -> ManagedByteArray<Self::Api, 32>
ripem 160
ripemd160(data: &ManagedBuffer) -> ManagedByteArray<Self::Api, 20>
签名验证功能:
验证 _ ed25519 _ 遗留 _ 托管
verify_ed25519_legacy_managed<const MAX_MESSAGE_LEN: usize>(key: &ManagedByteArray<Self::Api, 32>, message: &ManagedBuffer, signature: &ManagedByteArray<Self::Api, 64>) -> bool
验证 _bls
verify_bls(key: &[u8], message: &[u8], signature: &[u8]) -> bool
验证 _secp256k1
verify_secp256k1(key: &[u8], message: &[u8], signature: &[u8]) -> bool
验证 _ 定制 _secp256k1
verify_custom_secp256k1(key: &[u8], message: &[u8], signature: &[u8], hash_type: MessageHashType) -> bool
MessageHashType
是一个枚举,表示用于创建message
参数的哈希算法。如果消息是“纯文本”,请使用ECDSAPlainMsg
。
pub enum MessageHashType {
ECDSAPlainMsg,
ECDSASha256,
ECDSADoubleSha256,
ECDSAKeccak256,
ECDSARipemd160,
}
为了能够在没有动态分配的情况下使用散列函数,我们在 Rust 中使用了一个称为const generics
的概念。这允许函数作为泛型有一个常量值,而不是泛型中常见的特征类型。该值用于分配一个静态缓冲区,在该缓冲区中数据被临时复制,然后被传递给遗留 API。
要调用这样一个函数,调用应该是这样的:
let hash = self.crypto().sha256_legacy_managed::<200>(&data);
其中200
是data
的最大预期字节长度。
编码 _ secp256k1 _ der _ 签名
encode_secp256k1_der_signature(r: &[u8], s: &[u8]) -> BoxedBytes
根据提供的相应椭圆曲线参数创建签名。
发送 API
这个 API 可以通过self.send()
访问。它提供了发送代币、执行智能合约调用、调用内置函数等功能。
我们不会描述 API 中的每一个函数,因为那样会造成混乱。我们将只描述推荐使用的那些(因为它们大多是更复杂的低级函数的包装)。
对于智能合约到智能合约的调用,使用代理,如合约调用部分所述。
事不宜迟,让我们来看看可用的函数:
直达
direct(to: &ManagedAddress, token: &EgldOrEsdtTokenIdentifier, nonce: u64, amount: &BigUint)
使用一些可选的附加数据,对目标地址执行简单的 EGLD/ESDT/NFT 传输。如果要发送 EGLD,只需通过EgldOrEsdtTokenIdentifier::egld()
。对于 EGLD 和可替代 ESDT,nonce
都应该是 0。
如果目的地是不可支付的智能合约,这将失败,但是只有当目的地 SC 在同一个碎片中时,当前执行的交易才会失败,因此,对存储所做的任何改变都将持续。但是代币不会丢失,因为它们会自动返回。
即使无效的目标不会恢复,非法传输也会返回错误并恢复。非法转账是指会给 SC 留下特定代币的负余额的任何转账。
如果您不确定目的地的账户类型,您可以使用Blockchain API
中的is_smart_contract
功能。
如果您需要更多的控制,请使用direct_with_gas_limit
功能。
direct _ egld
direct_egld(to: &ManagedAddress, amount: &BigUint)
direct
函数的 EGLD-transfer 版本。
direct _ esdt
direct_esdt(to: &ManagedAddress, token_id: &TokenIdentifier, token_nonce: u64, amount: &BigUint)
direct
功能的 ESDT 专用版本。这样你就不用把TokenIdentifier
包装成EgldOrEsdtTokenIdentifier
了。
直接 _ 多
direct_multi(to: &ManagedAddress, payments: &ManagedVec<EsdtTokenPayment<Self::Api>>)
direct_esdt
功能的多传输版本。请记住,不能用这个函数传输 EGLD,只能传输 ESDTs。
变更 _ 所有者 _ 地址
change_owner_address(child_sc_address: &ManagedAddress, new_owner: &ManagedAddress)
将目标子合约的所有权更改为另一个地址。如果当前合约不是child_sc_address
合约的所有者,这将失败。
这也意味着当前合约将不能调用子合约的#[only_owner]
函数、升级或再次改变所有者。
esdt_local_mint(token: &TokenIdentifier, nonce: u64, amount: &BigUint)
允许同步铸造 ESDT/SFT(取决于现时)。之后继续执行。请注意,SC 必须设置了ESDTLocalMint
或ESDTNftAddQuantity
角色,否则将出现“不允许操作”的错误。
对于 sft,您必须在添加额外数量之前使用esdt_nft_create
。
此功能不能用于 NFTs。
esdt _ local _ burn
esdt_local_burn(token: &TokenIdentifier, nonce: u64, amount: &BigUint)
esdt_local_mint
的逆操作,永久删除代币。请注意,SC 必须设置了ESDTLocalBurn
或ESDTNftBurn
角色,否则会出现“不允许操作”的错误。
与 mint 函数不同,这可以用于 NFT。
esdt_nft_create<T: elrond_codec::TopEncode>(token: &TokenIdentifier, amount: &BigUint, name: &ManagedBuffer, royalties: &BigUint, hash: &ManagedBuffer, attributes: &T, uris: &ManagedVec< ManagedBuffer>) -> u64
创建一个新的 SFT/NFT,并返回其 nonce。
必须设置ESDTNftCreate
角色,否则将失败并显示“不允许操作”。
token
是 SFT/NFT 品牌的标识符。
amount
是要铸造的代币数量。对于 NFTs,这应该是“1”。
name
是代币的显示名称,将在浏览器、市场等中使用。
royalties
是一个介于 0 和 10,000 之间的数字,代表创作者获得的任何销售金额的百分比。这种表示用于能够具有更高的精度。例如,像55.66%
这样的百分比被存储为5566
。这些特许权使用费是不强制执行的,将主要用于“官方”NFT 市场。
hash
是代币的用户定义哈希。推荐值是 sha256(属性),但可以是任何值。
attributes
可以是任何可序列化的用户定义结构,更具体地说,可以是实现TopEncode
特征的任何类型。在撰写本文时,属性格式还没有真正的标准,但将来可能会改变。
uris
是 NFTs 视频/音频表示的链接列表,大多数情况下,这些是图像、视频或歌曲的链接。如果为空,框架将自动添加一个“空”URI。
esdt_nft_create_compact<T: elrond_codec::TopEncode>(token: &TokenIdentifier, amount: &BigUint, attributes: &T) -> u64
与esdt_nft_create
相同,但用默认值填充大多数参数。主要用于将 NFTs 作为信息手段而非展示目的的合约中。
出售 _nft
sell_nft(nft_id: &TokenIdentifier, nft_nonce: u64, nft_amount: &BigUint, buyer: &ManagedAddress, payment_token: &EgldOrEsdtTokenIdentifier, payment_nonce: u64, payment_amount: &BigUint) -> BigUint
将 SFTs/NFTs 发送到目标地址,同时自动计算并向创作者发送 NFT 版税。返回扣除版税后剩余的金额。
(nft_id, nft_nonce, nft_amount)
是将要发送到buyer
地址的 sft/NFT。
是用来支付创作者版税的代币。
这个函数的目的主要是用在类似市场的智能合约中,合约向用户出售 NFT。
nft_add_uri(token_id: &TokenIdentifier, nft_nonce: u64, new_uri: ManagedBuffer)
将 URI 添加到选定的 NFT。SC 必须拥有 NFT 并拥有能够使用该功能的ESDTRoleNFTAddURI
。
如果需要一次添加多个 URIs,可以使用nft_add_multiple_uri
函数,该函数以一个ManagedVec<ManagedBuffer>
作为参数。
NFT _ 更新 _ 属性
nft_update_attributes<T: TopEncode>(token_id: &TokenIdentifier, nft_nonce: u64, new_attributes: &T)
将所选 NFT 的属性更新为提供的值。SC 必须拥有 NFT 并拥有能够更新属性的ESDTRoleNFTUpdateAttributes
。
结论
尽管 elrond-wasm 中还有其他各种 API,但它们对用户来说大多是隐藏的。这些是您将在日常智能合约开发中使用的工具。