Question about the DIP-721-NFT-Container transferForm (Motoko)

I’m getting started with integrating NFT support into my project. I’m looking through the code for the dip-721-nft-containter. In particular, I’m looking at how NFT ownership is transferred. I see that there are methods for created transfer forms for an NFT, but where can i find the method that actually executes the transfer of the NFT on the blockchain.

A link to a sample project that achieves this would be greatly appreciated.

1 Like

Like with ERC-721, there are two transfer methods: transfer for 1st-party transfers and transferFrom for 3rd-party transfers. The former is used if the caller owns the NFT and wants to transfer it to someone else; the latter is used if the caller doesn’t own the NFT and is transferring it on behalf of its owner.

1 Like

I’m still not quite clear as to where the actual transfer of ownership is made on the blockchain. Is the transferFrom Function a helper method whose results are put into another function that actually executes the transfer on the blockchain? Or is the transferFrom Function, itself, the function that is handling the whole exchange operation?

And if it is the case that the transferFrom function is handling the entire exchange operation, how do other NFT exchanges and NFT wallets have any sort of shared awareness of the NFT and it’s owners.

Not quite sure I understand the question, please clarify if I answered the wrong question.

You can see how the transfer works here in lines 57-89: examples/ at master · dfinity/examples · GitHub

If you look at the (more fleshed out) Rust version of the NFT example, you can see how the transfer is triggered here (line 40): examples/ at master · dfinity/examples · GitHub. The intention is that someone manually (or automatically) calls the function from outside.

Ok, i guess I’m just confused on how the dip-721-nft-container Works altogether then.

I have a few clarifying questions that’ll help me if answered:

1.) Does each instance of the dip-721-nft-container Serve as a single NFT? Or does it serve as an NFT wallet that holds all of a single user’s NFT’s?
The stable var nfts = List.nil<Types.Nft>(); variable makes me think it’s a wallet that holds all of a users NFT’s, which contradicts my initial understanding of the
dip-721-nft-container‘s purpose as a canister that acts on other canisters, making them into a single NFT.

2.) there has to exist some sort of shared ledger that keeps track of the NFT’s and their owners. And NFT wallets must be able to query that shared ledger in order to render all NFT’s associated to a particular principal. Otherwise, Alice, who uses NFT wallet A built by company A, wouldn’t be able to send her NFT’s to Bob, who users NFT wallet B built by company B. My question is, where does that transaction happen?

To me, it looks like the transferFrom Method is merely updating the owner of the NFT within a single instance of the dip-721-nft-container actor class. Which is fine for displaying the correct ownership status for Alice, the sender of the NFT, but Bob’s wallet, built by another company with its own instances of the dip-721-nft-container, has no way For this change in ownership to be recorded without a shared ledger to query. What serves as that shared ledger? And how do i access it?

The canister serves a collection of NFTs, where each individual NFT can be owned by a separate person. I think an NFT wallet would then link out to all the separate NFTs an individual owns.

AFAIU keeping track of what you own is the job of your NFT wallet. The transferFromNotifyDip721 function would do the notification of the wallet once a transfer is completed, I suppose. Then the wallet knows that there’s a new NFT to display.

1 Like

Ok. That helps. Let me know if my current understanding is correct:

So, each NFT collection exists in its own canister. If NFT wallets would like to support NFT collections from other projects, they will have to make async calls to the canister that stores the NFT collection. The dip-721 standard is an implementation that is adopted by devs as a way to maintain uniformity for scenarios in which NFT wallet custodians would like to work in an interoperable manner.

How’d i do?

1 Like

That’s how I understand it as well :+1: