谁是 nft_transfer_call 中的接收者?
Posted
技术标签:
【中文标题】谁是 nft_transfer_call 中的接收者?【英文标题】:Who is the receiver in a nft_transfer_call? 【发布时间】:2021-10-08 15:06:46 【问题描述】:我有一个NFT
合约和一个Market
部署它。
我没有使用nft_transfer_call
接受出价,但现在将其添加。
在NFT
/Media
所有者接受投标的情况下,当前实施的流程是:
-
调用
[nft-contract].accept_bid(token_id, bidder)
开始跨合约调用
[market-contract].xcc_market_accept_bid(token_id, bidder, design.creator, design.owner_id, design.prev_owner)
市场负责支付股票、取消出价和回调NFT
[nft-contract].xcc_media_nft_transfer(token_id, receiver_id)
将招式NFT
/Media
转让给新的所有者和结局!
我知道这不是正确的方法,因为我应该使用 nft_transfer_call
,根据标准,这就是我理解的上述调用的方式:
[nft-contract].nft_transfer_call(
"receiver_id": $market_address, ? or $bidder
"token_id": $token_id,
"msg": "$token_id $bidder $creator $owner_id $prev_owner"
)
应该在内部传输令牌然后触发:
[market-contract].nft_on_transfer(
"sender_id": $sender_of_nft_transfer_call,
"previous_owner_id": $get_media_prev_owner_from_store,
"token_id": $token_id_passed_by_front_end,
"msg": "$token_id $bidder $creator $owner_id $prev_owner", // parameters for Market contract
)
分配支出、更新新股并最终回调:
[nft-contract].nft_resolve_transfer(
"sender_id": $sender_of_nft_transfer_call,
"receiver_id": $market_address, ? or $bidder,
"token_id": $token_id,
)
问题是在这种情况下receiver_id
是谁(市场还是新所有者)?我知道审批管理标准在这里可能是更好的解决方案,但我试图保持简单并通过转接电话解决它。
Market interface
【问题讨论】:
【参考方案1】:如果我正确阅读了您的代码,bidder
是两个函数中receiver_id
的值。来自 [docs][1]:
// * `receiver_id`: the valid NEAR account receiving the token
// Arguments:
// * `receiver_id`: the valid NEAR account receiving the token.
// * `token_id`: the token to send.
// * `approval_id`: expected approval ID. A number smaller than
// 2^53, and therefore representable as JSON. See Approval Management
// standard for full explanation.
// * `memo` (optional): for use cases that may benefit from indexing or
// providing information for a transfer.
// * `msg`: specifies information needed by the receiving contract in
// order to properly handle the transfer. Can indicate both a function to
// call and the parameters to pass to that function.
function nft_transfer_call(
receiver_id: string,
token_id: string,
approval_id: number|null,
memo: string|null,
msg: string,
): Promise
应该匹配nft_resolve_transfer()
中的参数
// * `receiver_id`: the `receiver_id` argument given to `nft_transfer_call`
// Arguments:
// * `sender_id`: the sender of `ft_transfer_call`
// * `receiver_id`: the `receiver_id` argument given to `nft_transfer_call`
// * `token_id`: the `token_id` argument given to `ft_transfer_call`
// * `approved_token_ids`: if using Approval Management, contract MUST provide
// set of original approved accounts in this argument, and restore these
// approved accounts in case of revert.
//
// Returns true if token was successfully transferred to `receiver_id`.
function nft_resolve_transfer(
owner_id: string,
receiver_id: string,
token_id: string,
approved_account_ids: null|string[],
): boolean
[1]: https://nomicon.io/Standards/NonFungibleToken/Core.html
【讨论】:
这是正确的。我注意到在这些 cmets 中阅读代码并不容易,因此我将在单独的答案中进行扩展。对于可能会发现这一点的人,请注意 BenTheHumanMan 在这里引用了 Nomicon 规范文档:nomicon.io/Standards/NonFungibleToken/Core.html#nft-interface【参考方案2】:正如 BenTheHumanMan 所说,receiver_id
将是相同的。
这是来自 Rust 示例的 sn-p:
fn nft_transfer_call(
&mut self,
receiver_id: AccountId,
token_id: TokenId,
approval_id: Option<u64>,
memo: Option<String>,
msg: String,
) -> PromiseOrValue<bool>
assert_one_yocto();
let sender_id = env::predecessor_account_id();
let (old_owner, old_approvals) =
self.internal_transfer(&sender_id, &receiver_id, &token_id, approval_id, memo);
// Initiating receiver's call and the callback
ext_receiver::nft_on_transfer(
sender_id.clone(),
old_owner.clone(),
token_id.clone(),
msg,
&receiver_id,
NO_DEPOSIT,
env::prepaid_gas() - GAS_FOR_FT_TRANSFER_CALL,
)
.then(ext_self::nft_resolve_transfer(
old_owner,
receiver_id,
token_id,
old_approvals,
&env::current_account_id(),
NO_DEPOSIT,
GAS_FOR_RESOLVE_TRANSFER,
))
.into()
请注意,我们使用的是最初提供给函数的 receiver_id
,然后将其传递给回调 (nft_resolve_transfer
)。
但也许为了更直接地回答您的问题……如果您让人们对 NFT 进行投标,则可能不需要使用转接和呼叫功能。在不了解出价如何运作的详细信息的情况下,我认为您说得对,批准更合适。
有一个示例in Nomicon 可能会有所帮助。请注意,这链接到可替代令牌而不是不可替代令牌,因为我相信这更容易理解。链接页面涉及以下场景:
Alice 需要发出 1 笔交易,而典型的托管工作流程则需要 2 笔。
简而言之……假设我想为一项服务支付 5 个可替代代币,比如说一个预言机。我向一个预言机合约支付了 5 个可替代代币,作为回报,他们会存储我的请求,这可能会被链下服务接收并响应。
为了:
-
发送我的链下服务请求
发送可替代代币
使用审批系统的典型工作流程是:
-
我允许预言机从我这里拿走 5 个可替代代币。
我发送了一个请求,预言机试图从我这里拿走这 5 个可替代令牌。
如果成功,则存储请求,如果不成功,则显示“您需要允许我从您那里取 5 个令牌”
这不是很好,需要多次交易。在这种情况下,我可以使用转接和呼叫功能来简化它。它基本上会说,“嘿,可替代代币合约,将 5 个代币转移到预言机,然后根据我在 msg
参数中提供的额外信息发送它们。” (也许msg
包含诸如我有什么类型的请求、请求详细信息、我不再需要链下响应等多长时间等信息。)
退出可替代令牌示例,同样的事情也适用于不可替代令牌。转接呼叫的用例不太简单,可能无法满足所有需求。
请参阅NFT Approval Management standard spec 了解有关该方法的更多详细信息,这可能是您想要的拍卖方式。
【讨论】:
以上是关于谁是 nft_transfer_call 中的接收者?的主要内容,如果未能解决你的问题,请参考以下文章