Error: value of type &NftMarketPlace.saleCollection{NftMarketPlace.saleCollectionPublic}? has no member purchase

44 Views Asked by At

let payment <- acct.borrow<&FlowToken.Vault>(from: /storage/flowTokenVault)!.withdraw(amount: price) as! @FlowToken.Vault saleCollection.purchase(id: id, receipientCollection: recipientCollection, payment: <- payment) }

my whole cadence code :https://github.com/Wiswa14/flow-MarketPlace/tree/master

This transaction code is for purchase a nft from a collection public path

3

There are 3 best solutions below

0
Jacob Tucker On

You are borrowing the saleCollection like this:

let saleCollection = getAccount(account).getCapability(/public/MySaleCollection)
                                           .borrow<&NftMarketPlace.saleCollection{NftMarketPlace.saleCollectionPublic}>()

It looks like the error is because it is an optional type (the ? at the end of the type), and you are not unwrapping it. The reason it is an optional is because the borrow will fail if the user does not have a sale collection there.

There are two ways to unwrap the optional:

1. Force-Unwrap Operator (!)

When you borrow the saleCollection, put a force-unwrap operator ! at the end and it will become a non-optional type, like so:

let saleCollection = getAccount(account).getCapability(/public/MySaleCollection)
                                           .borrow<&NftMarketPlace.saleCollection{NftMarketPlace.saleCollectionPublic}>()!

2. panic

You can also put a panic statement to unwrap the optional and put a more clear error message:

let saleCollection = getAccount(account).getCapability(/public/MySaleCollection)
                                           .borrow<&NftMarketPlace.saleCollection{NftMarketPlace.saleCollectionPublic}>()
?? panic("The user does not have a sale collection here.")
1
Supun Setunga On

In addition to what @Jacob said in the previous answer, there's a third way, with optional binding:

let optionalSaleCollection = getAccount(account).getCapability(/public/MySaleCollection)
                                                .borrow<&NftMarketPlace.saleCollection{NftMarketPlace.saleCollectionPublic}>()

if let saleCollection = optionalSaleCollection {
    // Things to do when `saleCollection` is not `nil`
} else {
    // Things to do if `optionalSaleCollection` is nil.
    // i.e: failed to borrow the value.
}

This is better suited if you want to gracefully handle the case where the value doesn't exist in the storage, or failed to borrow for some reason. But if you know for sure the value would be there, or want to abort the program/transaction if it fails to borrow, then one of the methods suggested by @Jacob would work just fine.

0
turbolent On

Joshua Hannan wrote a great blog post about working with optionals in Cadence: https://flow.com/engineering-blogs/optionals-in-cadence-not-optional

In addition to the options mentioned in the existing answers, there is a third option: optional chaining. Optional chaining is especially useful if you are only planning to access one or a couple of few fields/functions of the optional value.