Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NFL-395 Optional serial when minting #23

Merged
merged 3 commits into from
Oct 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 11 additions & 6 deletions contracts/AllDay.cdc
Original file line number Diff line number Diff line change
Expand Up @@ -449,19 +449,24 @@ pub contract AllDay: NonFungibleToken {
// Mint a Moment NFT in this edition, with the given minting mintingDate.
// Note that this will panic if the max mint size has already been reached.
//
pub fun mint(): @AllDay.NFT {
pub fun mint(serialNumber: UInt64?): @AllDay.NFT {
pre {
self.numMinted != self.maxMintSize: "max number of minted moments has been reached"
}

var serial = self.numMinted + 1 as UInt64
if(self.maxMintSize == nil) {
serial = serialNumber!
}

// Create the Moment NFT, filled out with our information
let momentNFT <- create NFT(
id: AllDay.totalSupply + 1,
editionID: self.id,
serialNumber: self.numMinted + 1
serialNumber: serial
)
AllDay.totalSupply = AllDay.totalSupply + 1
// Keep a running total (you'll notice we used this as the serial number)
// Keep a running total (you'll notice we used this as the serial number for closed editions)
self.numMinted = self.numMinted + 1 as UInt64

return <- momentNFT
Expand Down Expand Up @@ -930,7 +935,7 @@ pub contract AllDay: NonFungibleToken {
// Mint a single NFT
// The Edition for the given ID must already exist
//
pub fun mintNFT(editionID: UInt64): @AllDay.NFT
pub fun mintNFT(editionID: UInt64, serialNumber: UInt64?): @AllDay.NFT
}

// A resource that allows managing metadata and minting NFTs
Expand Down Expand Up @@ -1087,12 +1092,12 @@ pub contract AllDay: NonFungibleToken {
// Mint a single NFT
// The Edition for the given ID must already exist
//
pub fun mintNFT(editionID: UInt64): @AllDay.NFT {
pub fun mintNFT(editionID: UInt64, serialNumber: UInt64?): @AllDay.NFT {
pre {
// Make sure the edition we are creating this NFT in exists
AllDay.editionByID.containsKey(editionID): "No such EditionID"
}
return <- self.borrowEdition(id: editionID).mint()
return <- self.borrowEdition(id: editionID).mint(serialNumber: serialNumber)
}
}

Expand Down
46 changes: 41 additions & 5 deletions lib/go/test/allday_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,7 @@ func TestMomentNFTs(t *testing.T) {
b,
contracts,
uint64(1),
nil,
userAddress,
uint64(1),
uint64(1),
Expand All @@ -444,6 +445,7 @@ func TestMomentNFTs(t *testing.T) {
b,
contracts,
uint64(1),
nil,
userAddress,
uint64(2),
uint64(2),
Expand All @@ -457,9 +459,10 @@ func TestMomentNFTs(t *testing.T) {
b,
contracts,
uint64(2),
uint64Ptr(2023),
userAddress,
uint64(3),
uint64(1),
uint64(2023),
false,
)
})
Expand All @@ -470,9 +473,10 @@ func TestMomentNFTs(t *testing.T) {
b,
contracts,
uint64(2),
uint64Ptr(2023),
userAddress,
uint64(4),
uint64(2),
uint64(2023),
false,
)
})
Expand All @@ -483,6 +487,7 @@ func TestMomentNFTs(t *testing.T) {
b,
contracts,
uint64(1),
nil,
userAddress,
uint64(3),
uint64(3),
Expand All @@ -496,6 +501,7 @@ func TestMomentNFTs(t *testing.T) {
b,
contracts,
uint64(3),
nil,
userAddress,
uint64(1),
uint64(1),
Expand All @@ -509,6 +515,7 @@ func testMintMomentNFT(
b *emulator.Blockchain,
contracts Contracts,
editionID uint64,
serialNumber *uint64,
userAddress flow.Address,
shouldBeID uint64,
shouldBeSerialNumber uint64,
Expand All @@ -523,6 +530,7 @@ func testMintMomentNFT(
contracts,
userAddress,
editionID,
serialNumber,
shouldRevert,
)

Expand Down Expand Up @@ -558,7 +566,7 @@ func TestMomentNFTMetadataViews(t *testing.T) {
userAddress, userSigner := createAccount(t, b)
setupAllDay(t, b, userAddress, userSigner, contracts)
createTestEditions(t, b, contracts)
mintMomentNFT(t, b, contracts, userAddress /*editionID*/, 1 /*shouldRevert*/, false)
mintMomentNFT(t, b, contracts, userAddress /*editionID*/, 1, nil /*shouldRevert*/, false)

t.Run("Should be able to get moment's metadata", func(t *testing.T) {
result := getMomentNFTMetadata(t, b, contracts, userAddress, 1, false)
Expand Down Expand Up @@ -676,7 +684,7 @@ func TestUpdatePlayDescription(t *testing.T) {
userAddress, userSigner := createAccount(t, b)
setupAllDay(t, b, userAddress, userSigner, contracts)
createTestEditions(t, b, contracts)
mintMomentNFT(t, b, contracts, userAddress /*editionID*/, 1 /*shouldRevert*/, false)
mintMomentNFT(t, b, contracts, userAddress /*editionID*/, 1, nil /*shouldRevert*/, false)

t.Run("Should be able to update play's description", func(t *testing.T) {
result := getMomentNFTMetadata(t, b, contracts, userAddress, 1, false)
Expand Down Expand Up @@ -706,7 +714,7 @@ func TestUpdatePlayDynamicMetadata(t *testing.T) {
userAddress, userSigner := createAccount(t, b)
setupAllDay(t, b, userAddress, userSigner, contracts)
createTestEditions(t, b, contracts)
mintMomentNFT(t, b, contracts, userAddress /*editionID*/, 1 /*shouldRevert*/, false)
mintMomentNFT(t, b, contracts, userAddress /*editionID*/, 1, nil /*shouldRevert*/, false)

t.Run("Should be able to update play's dynamic metadata", func(t *testing.T) {
//Validate initial Display
Expand Down Expand Up @@ -745,3 +753,31 @@ func TestUpdatePlayDynamicMetadata(t *testing.T) {
}
})
}

func TestMintMomentMulti(t *testing.T) {
b := newEmulator()
contracts := AllDayDeployContracts(t, b)
userAddress, userSigner := createAccount(t, b)
setupAllDay(t, b, userAddress, userSigner, contracts)
createTestEditions(t, b, contracts)
// edition 1 has a maxSize while edition 2 does not
editions := []uint64{1, 2}
serialNumbers := []*uint64{nil, uint64Ptr(2023)}

mintMomentNFTMulti(t, b, contracts, userAddress /*editionID*/, editions, serialNumbers /*shouldRevert*/, false)

t.Run("Should have a serial number of 1", func(t *testing.T) {
nft := getMomentNFTProperties(t, b, contracts, userAddress, 1)
assert.Equal(t, uint64(1), nft.EditionID)
assert.Equal(t, uint64(1), nft.SerialNumber)
})
t.Run("Should have a serial number of 2023", func(t *testing.T) {
nft := getMomentNFTProperties(t, b, contracts, userAddress, 2)
assert.Equal(t, uint64(2), nft.EditionID)
assert.Equal(t, uint64(2023), nft.SerialNumber)
})
}

func uint64Ptr(i uint64) *uint64 {
return &i
}
2 changes: 1 addition & 1 deletion lib/go/test/templates.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ const (

// Moment NFTs
AllDayMintMomentNFTPath = AllDayTransactionsRootPath + "/admin/nfts/mint_moment_nft.cdc"
AllDayMintMomentNFTMultiPath = AllDayTransactionsRootPath + "/admin/nfts/mint_moment_nft_multi.cdc"
AllDayMintMomentNFTMultiPath = AllDayTransactionsRootPath + "/admin/nfts/mint_moment_nfts_multi.cdc"
AllDayTransferNFTPath = AllDayTransactionsRootPath + "/user/transfer_moment_nft.cdc"
AllDayReadMomentNFTSupplyPath = AllDayScriptsRootPath + "/nfts/read_moment_nft_supply.cdc"
AllDayReadMomentNFTPropertiesPath = AllDayScriptsRootPath + "/nfts/read_moment_nft_properties.cdc"
Expand Down
50 changes: 50 additions & 0 deletions lib/go/test/transactions.go
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,7 @@ func mintMomentNFT(
contracts Contracts,
recipientAddress flow.Address,
editionID uint64,
serialNumber *uint64,
shouldRevert bool,
) {
tx := flow.NewTransaction().
Expand All @@ -310,6 +311,55 @@ func mintMomentNFT(
AddAuthorizer(contracts.AllDayAddress)
tx.AddArgument(cadence.BytesToAddress(recipientAddress.Bytes()))
tx.AddArgument(cadence.NewUInt64(editionID))
sNumber := cadence.NewOptional(nil)
if serialNumber != nil {
sNumber = cadence.NewOptional(cadence.NewUInt64(*serialNumber))
}
tx.AddArgument(sNumber)

signer, err := b.ServiceKey().Signer()
require.NoError(t, err)
signAndSubmit(
t, b, tx,
[]flow.Address{b.ServiceKey().Address, contracts.AllDayAddress},
[]crypto.Signer{signer, contracts.AllDaySigner},
shouldRevert,
)
}

func mintMomentNFTMulti(
t *testing.T,
b *emulator.Blockchain,
contracts Contracts,
recipientAddress flow.Address,
editionIDs []uint64,
serialNumbers []*uint64,
shouldRevert bool,
) {
tx := flow.NewTransaction().
SetScript(loadAllDayMintMomentNFTMultiTransaction(contracts)).
SetGasLimit(900).
SetProposalKey(b.ServiceKey().Address, b.ServiceKey().Index, b.ServiceKey().SequenceNumber).
SetPayer(b.ServiceKey().Address).
AddAuthorizer(contracts.AllDayAddress)
tx.AddArgument(cadence.BytesToAddress(recipientAddress.Bytes()))
counts := []cadence.Value{}
cEditionIDs := []cadence.Value{}
for _, id := range editionIDs {
cEditionIDs = append(cEditionIDs, cadence.NewUInt64(id))
counts = append(counts, cadence.NewUInt64(1))
}
cSerialNumbers := []cadence.Value{}
for _, sn := range serialNumbers {
if sn != nil {
cSerialNumbers = append(cSerialNumbers, cadence.NewOptional(cadence.NewUInt64(*sn)))
} else {
cSerialNumbers = append(cSerialNumbers, cadence.NewOptional(nil))
}
}
tx.AddArgument(cadence.NewArray(cEditionIDs))
tx.AddArgument(cadence.NewArray(counts))
tx.AddArgument(cadence.NewArray(cSerialNumbers))

signer, err := b.ServiceKey().Signer()
require.NoError(t, err)
Expand Down
4 changes: 2 additions & 2 deletions transactions/admin/nfts/mint_moment_nft.cdc
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import NonFungibleToken from "../../../contracts/NonFungibleToken.cdc"
import AllDay from "../../../contracts/AllDay.cdc"

transaction(recipientAddress: Address, editionID: UInt64) {
transaction(recipientAddress: Address, editionID: UInt64, serialNumber: UInt64?) {

// local variable for storing the minter reference
let minter: &{AllDay.NFTMinter}
Expand All @@ -24,7 +24,7 @@ transaction(recipientAddress: Address, editionID: UInt64) {

execute {
// mint the NFT and deposit it to the recipient's collection
let momentNFT <- self.minter.mintNFT(editionID: editionID)
let momentNFT <- self.minter.mintNFT(editionID: editionID, serialNumber: serialNumber)
self.recipient.deposit(token: <- (momentNFT as @NonFungibleToken.NFT))
}
}
Expand Down
5 changes: 3 additions & 2 deletions transactions/admin/nfts/mint_moment_nfts_multi.cdc
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import NonFungibleToken from "../../../contracts/NonFungibleToken.cdc"
import AllDay from "../../../contracts/AllDay.cdc"

transaction(recipientAddress: Address, editionIDs: [UInt64], counts: [UInt64]) {
transaction(recipientAddress: Address, editionIDs: [UInt64], counts: [UInt64], serialNumbers: [UInt64?]) {

// local variable for storing the minter reference
let minter: &{AllDay.NFTMinter}
Expand All @@ -25,6 +25,7 @@ transaction(recipientAddress: Address, editionIDs: [UInt64], counts: [UInt64]) {

pre {
editionIDs.length == counts.length: "must pass arrays of same length"
editionIDs.length == serialNumbers.length: "must pass arrays of same length"
}

execute {
Expand All @@ -33,7 +34,7 @@ transaction(recipientAddress: Address, editionIDs: [UInt64], counts: [UInt64]) {
var remaining = counts[i]
while remaining > 0 {
// mint the NFT and deposit it to the recipient's collection
self.recipient.deposit(token: <- self.minter.mintNFT(editionID: editionIDs[i]))
self.recipient.deposit(token: <- self.minter.mintNFT(editionID: editionIDs[i], serialNumber: serialNumbers[i]))
remaining = remaining - 1
}
i = i + 1
Expand Down