Skip to content

Commit

Permalink
save cap on storage (#264)
Browse files Browse the repository at this point in the history
* save cap on storage

* fix var / entitlements

* add comments and V1 Sale handling to create and start sale collection (#266)

---------

Co-authored-by: Joshua Hannan <[email protected]>
  • Loading branch information
fkenji and joshuahannan authored Aug 30, 2024
1 parent 19d37ae commit b42875f
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 13 deletions.
6 changes: 3 additions & 3 deletions lib/go/templates/internal/assets/assets.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

56 changes: 46 additions & 10 deletions transactions/marketV3/create_start_sale.cdc
Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +4,69 @@ import TopShot from 0xTOPSHOTADDRESS
import Market from 0xMARKETADDRESS
import NonFungibleToken from 0xNFTADDRESS

/// This transaction creates a V3 Sale Collection
/// in a user's account and lists a Moment for Sale in that collection
/// If a user already has a V3 Sale Collection
/// the transaction only lists the moment for sale
///
/// When creating a V3 Sale Collection, if the user already has a V1 Sale Collection,
/// the transaction will create and store a provider capability for that V1 Sale Collection
/// to be used with the V3 Sale Collection
transaction(tokenReceiverPath: PublicPath, beneficiaryAccount: Address, cutPercentage: UFix64, momentID: UInt64, price: UFix64) {

prepare(acct: auth(Storage, Capabilities) &Account) {
// check to see if a v3 sale collection already exists
if acct.storage.borrow<&TopShotMarketV3.SaleCollection>(from: TopShotMarketV3.marketStoragePath) == nil {
// If the V3 Sale Collection does not exist, set up a new one
// get the fungible token capabilities for the owner and beneficiary
let ownerCapability = acct.capabilities.get<&{FungibleToken.Receiver}>(tokenReceiverPath)!
let beneficiaryCapability = getAccount(beneficiaryAccount).capabilities.get<&{FungibleToken.Receiver}>(tokenReceiverPath)!
let ownerCapability = acct.capabilities.get<&{FungibleToken.Receiver}>(tokenReceiverPath)
if !ownerCapability.check() {
panic("Could not get the owner's FungibleToken.Receiver capability from ".concat(tokenReceiverPath.toString()))
}
let beneficiaryCapability = getAccount(beneficiaryAccount).capabilities.get<&{FungibleToken.Receiver}>(tokenReceiverPath)
if !beneficiaryCapability.check() {
panic("Could not get the beneficiary's FungibleToken.Receiver capability from ".concat(tokenReceiverPath.toString()))
}

let ownerCollection = acct.capabilities.storage.issue<auth(NonFungibleToken.Withdraw,NonFungibleToken.Update) &TopShot.Collection>(/storage/MomentCollection)
// Get the owner's TopShot Collection Provider Capability that
// allows the V3 sale collection to withdraw when sales are made
var ownerCollection = acct.storage.copy<Capability<auth(NonFungibleToken.Withdraw, NonFungibleToken.Update) &TopShot.Collection>>(from: /storage/MomentCollectionCap)
if ownerCollection == nil {
// If the moment collection capabilitity does not already exist,
// Issue a new one and store it in the standard private moment collection capability path
ownerCollection = acct.capabilities.storage.issue<auth(NonFungibleToken.Withdraw, NonFungibleToken.Update) &TopShot.Collection>(/storage/MomentCollection)
acct.storage.save(ownerCollection, to: /storage/MomentCollectionCap)
}

// get a capability for the v1 collection
var v1SaleCollection: Capability<auth(Market.Create, NonFungibleToken.Withdraw, Market.Update) &Market.SaleCollection>? = nil
if acct.storage.borrow<&Market.SaleCollection>(from: /storage/topshotSaleCollection) != nil {
v1SaleCollection = acct.capabilities.storage.issue<auth(Market.Create, NonFungibleToken.Withdraw, Market.Update) &Market.SaleCollection>(/storage/topshotSaleCollection)
// Only accounts that existed before the V3 Sale Collection contract was deployed
// will have this
var v1SaleCollection = acct.storage.copy<Capability<auth(Market.Create, NonFungibleToken.Withdraw, Market.Update) &Market.SaleCollection>>(from: /storage/topshotSaleCollectionCap)
if v1SaleCollection == nil {
// If the account doesn't have a V1 Sale Collection capability already,
// first check if they even have a V1 Sale Collection at all
if acct.storage.borrow<auth(Market.Create) &Market.SaleCollection>(from: /storage/topshotSaleCollection) != nil {
// If they have a V1 Sale Collection, issue a capability for it
// and store it in storage
v1SaleCollection = acct.capabilities.storage.issue<auth(Market.Create, NonFungibleToken.Withdraw, Market.Update) &Market.SaleCollection>(/storage/topshotSaleCollection)
acct.storage.save(v1SaleCollection, to: /storage/topshotSaleCollectionCap)
}
}

// create a new sale collection
let topshotSaleCollection <- TopShotMarketV3.createSaleCollection(ownerCollection: ownerCollection,
// V1SaleCollection will still be `nil` here if a V1 Sale Collection
// did not exist in the authorizer's account
// We can force-unwrap `ownerCollection` because it was already guaranteed to be non-`nil` above
let topshotV3SaleCollection <- TopShotMarketV3.createSaleCollection(ownerCollection: ownerCollection!,
ownerCapability: ownerCapability,
beneficiaryCapability: beneficiaryCapability,
cutPercentage: cutPercentage,
marketV1Capability: v1SaleCollection)

// save it to storage
acct.storage.save(<-topshotSaleCollection, to: TopShotMarketV3.marketStoragePath)
acct.storage.save(<-topshotV3SaleCollection, to: TopShotMarketV3.marketStoragePath)

// create a public link to the sale collection
acct.capabilities.publish(
Expand All @@ -40,10 +77,9 @@ transaction(tokenReceiverPath: PublicPath, beneficiaryAccount: Address, cutPerce

// borrow a reference to the sale
let topshotSaleCollection = acct.storage.borrow<auth(TopShotMarketV3.Create) &TopShotMarketV3.SaleCollection>(from: TopShotMarketV3.marketStoragePath)
?? panic("Could not borrow from sale in storage")
?? panic("Could not borrow the owner's Top Shot V3 Sale Collection in storage from ".concat(TopShotMarketV3.marketStoragePath.toString()))

// put the moment up for sale
topshotSaleCollection.listForSale(tokenID: momentID, price: price)

}
}

0 comments on commit b42875f

Please sign in to comment.