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

add creator to DropTypes.DropSummary struct #41

Merged
merged 3 commits into from
Sep 20, 2024
Merged
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
42 changes: 39 additions & 3 deletions contracts/DropTypes.cdc
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@ import "FlowtyDrops"
import "MetadataViews"
import "ViewResolver"
import "AddressUtils"
import "ContractManager"

access(all) contract DropTypes {
access(all) struct Display {
@@ -34,6 +35,7 @@ access(all) contract DropTypes {
access(all) let minterCount: Int
access(all) let commissionRate: UFix64
access(all) let nftType: String
access(all) let creator: Address?

access(all) let address: Address?
access(all) let mintedByAddress: Int?
@@ -55,10 +57,12 @@ access(all) contract DropTypes {
nftType: Type,
address: Address?,
phases: [PhaseSummary],
royaltyRate: UFix64
royaltyRate: UFix64,
creator: Address?
) {
self.id = id
self.display = Display(display)
self.creator = creator

self.medias = []
for m in medias?.items ?? [] {
@@ -169,6 +173,8 @@ access(all) contract DropTypes {
let contractAddress = AddressUtils.parseAddress(nftType)!
let contractName = segments[2]

let creator = self.getCreatorAddress(contractAddress)

let resolver = getAccount(contractAddress).contracts.borrow<&{ViewResolver}>(name: contractName)
if resolver == nil {
return nil
@@ -224,7 +230,8 @@ access(all) contract DropTypes {
nftType: CompositeType(dropDetails.nftType)!,
address: minter,
phases: phaseSummaries,
royaltyRate: royaltyRate
royaltyRate: royaltyRate,
creator: creator
)

return dropSummary
@@ -235,6 +242,8 @@ access(all) contract DropTypes {
let segments = nftTypeIdentifier.split(separator: ".")
let contractAddress = AddressUtils.parseAddress(nftType)!
let contractName = segments[2]

let creator = self.getCreatorAddress(contractAddress)

let resolver = getAccount(contractAddress).contracts.borrow<&{ViewResolver}>(name: contractName)
if resolver == nil {
@@ -297,10 +306,37 @@ access(all) contract DropTypes {
nftType: CompositeType(dropDetails.nftType)!,
address: minter,
phases: phaseSummaries,
royaltyRate: royaltyRate
royaltyRate: royaltyRate,
creator: creator
))
}

return summaries
}

access(all) fun getCreatorAddress(_ contractAddress: Address): Address? {
// We look for a two-way relationship between creator and collection. A contract can expose an address at ContractManager.OwnerPublicPath
// specifying the owning account. If found, we will check that same account for a &ContractManager.Manager resource at ContractManager.PublicPath,
// which, when borrowed, can return its underlying account address using &Manager.getAccount().
//
// If the addresses match, we consider this account to be the creator of a drop
let tmp = getAccount(contractAddress).capabilities.borrow<&Address>(ContractManager.OwnerPublicPath)
if tmp == nil {
return nil
}

let creator = *(tmp!)
let manager = getAccount(creator).capabilities.borrow<&ContractManager.Manager>(ContractManager.PublicPath)
if manager == nil {
return nil
}

let contractManagerAccount = manager!.getAccount()

if contractManagerAccount.address != contractAddress {
return nil
}

return creator
}
}
19 changes: 5 additions & 14 deletions flow.json
Original file line number Diff line number Diff line change
@@ -12,27 +12,18 @@
},
"emulator-account": {
"address": "f8d6e0586b0a20c7",
"key": {
"type": "file",
"location": "emulator-account.pkey"
}
"key": "f2e846bd4c1fbf17839ae59e111c6b1c98579eda7a841412f102d6621ec671cb"
},
"emulator-ft": {
"address": "ee82856bf20e2aa6",
"key": {
"type": "file",
"location": "emulator-account.pkey"
}
"key": "f2e846bd4c1fbf17839ae59e111c6b1c98579eda7a841412f102d6621ec671cb"
},
"emulator-flowtoken": {
"address": "0ae53cb6e3f42a79",
"key": {
"type": "file",
"location": "emulator-account.pkey"
}
"key": "f2e846bd4c1fbf17839ae59e111c6b1c98579eda7a841412f102d6621ec671cb"
},
"flowty-drops-testnet": {
"address": "0x772a10c786851a1b",
"address": "0x155bce6ac93f3e00",
"key": {
"type": "google-kms",
"index": 0,
@@ -42,7 +33,7 @@
}
},
"droptypes-testnet": {
"address": "0x22f23883bf122007",
"address": "0x53ff16309e318ae2",
"key": {
"type": "google-kms",
"index": 0,
17 changes: 17 additions & 0 deletions tests/ContractManager_tests.cdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import Test
import "./test_helpers.cdc"
import "ContractManager"

access(all) fun setup() {
deployAll()
}

access(all) fun test_SetupContractManager() {
let acct = Test.createAccount()
mintFlowTokens(acct, 10.0)

txExecutor("contract-manager/setup.cdc", [acct], [1.0])

let savedEvent = Test.eventsOfType(Type<ContractManager.ManagerSaved>()).removeLast() as! ContractManager.ManagerSaved
Test.assertEqual(acct.address, savedEvent.ownerAddress)
}
14 changes: 7 additions & 7 deletions tests/FlowtyDrops_tests.cdc
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@ access(all) fun setup() {
}

access(all) fun afterEach() {
txExecutor("drops/remove_all_drops.cdc", [openEditionAccount], [], nil, nil)
txExecutor("drops/remove_all_drops.cdc", [openEditionAccount], [])
}

access(all) fun testImports() {
@@ -91,7 +91,7 @@ access(all) fun test_OpenEditionNFT_EditPhaseDetails() {
let currentTime = getCurrentTime()
let newStart = UInt64(currentTime + 5.0)

txExecutor("drops/edit_timebased_phase_start_and_end.cdc", [openEditionAccount], [dropID, 0, newStart, newStart + 5], nil, nil)
txExecutor("drops/edit_timebased_phase_start_and_end.cdc", [openEditionAccount], [dropID, 0, newStart, newStart + 5])
Test.assertEqual(false, hasDropPhaseStarted(nftTypeIdentifier: openEditionNftIdentifier(), dropID: dropID, phaseIndex: 0))
Test.assertEqual(false, hasDropPhaseEnded(nftTypeIdentifier: openEditionNftIdentifier(), dropID: dropID, phaseIndex: 0))

@@ -109,14 +109,14 @@ access(all) fun test_OpenEditionNFT_EditPrice() {
let dropID = createDefaultTimeBasedOpenEditionDrop()
Test.assertEqual(1.0, getPriceAtPhase(nftTypeIdentifier: openEditionNftIdentifier(), dropID: dropID, phaseIndex: 0, minter: openEditionAccount.address, numToMint: 1, paymentIdentifier: flowTokenIdentifier()))

txExecutor("drops/edit_flat_price.cdc", [openEditionAccount], [dropID, 0, 2.0], nil, nil)
txExecutor("drops/edit_flat_price.cdc", [openEditionAccount], [dropID, 0, 2.0])
Test.assertEqual(2.0, getPriceAtPhase(nftTypeIdentifier: openEditionNftIdentifier(), dropID: dropID, phaseIndex: 0, minter: openEditionAccount.address, numToMint: 1, paymentIdentifier: flowTokenIdentifier()))
}

access(all) fun test_OpenEditionNFT_EditMaxPerMint() {
let dropID = createDefaultTimeBasedOpenEditionDrop()
Test.assertEqual(true, canMintAtPhase(nftTypeIdentifier: openEditionNftIdentifier(), dropID: dropID, phaseIndex: 0, minter: openEditionAccount.address, numToMint: 10, totalMinted: 0, paymentIdentifier: flowTokenIdentifier()))
txExecutor("drops/edit_address_verifier_max_per_mint.cdc", [openEditionAccount], [dropID, 0, 5], nil, nil)
txExecutor("drops/edit_address_verifier_max_per_mint.cdc", [openEditionAccount], [dropID, 0, 5])

Test.assertEqual(false, canMintAtPhase(nftTypeIdentifier: openEditionNftIdentifier(), dropID: dropID, phaseIndex: 0, minter: openEditionAccount.address, numToMint: 10, totalMinted: 0, paymentIdentifier: flowTokenIdentifier()))
Test.assertEqual(true, canMintAtPhase(nftTypeIdentifier: openEditionNftIdentifier(), dropID: dropID, phaseIndex: 0, minter: openEditionAccount.address, numToMint: 5, totalMinted: 0, paymentIdentifier: flowTokenIdentifier()))
@@ -131,13 +131,13 @@ access(all) fun test_OpenEditionNFT_GetActivePhases() {
access(all) fun test_OpenEditionNFT_addPhase() {
let dropID = createDefaultTimeBasedOpenEditionDrop()

txExecutor("drops/add_free_phase.cdc", [openEditionAccount], [dropID, nil, nil, "https://example.com/fake_image.jpg"], nil, nil)
txExecutor("drops/add_free_phase.cdc", [openEditionAccount], [dropID, nil, nil, "https://example.com/fake_image.jpg"])
let phaseEvent = Test.eventsOfType(Type<FlowtyDrops.PhaseAdded>()).removeLast() as! FlowtyDrops.PhaseAdded

var activePhaseIDs = scriptExecutor("get_active_phases.cdc", [openEditionNftIdentifier(), dropID])! as! [UInt64]
Test.assert(activePhaseIDs.contains(phaseEvent.id), message: "unexpected active phase length")

txExecutor("drops/remove_last_phase.cdc", [openEditionAccount], [dropID, nil, nil], nil, nil)
txExecutor("drops/remove_last_phase.cdc", [openEditionAccount], [dropID, nil, nil])
activePhaseIDs = scriptExecutor("get_active_phases.cdc", [openEditionNftIdentifier(), dropID])! as! [UInt64]
Test.assert(!activePhaseIDs.contains(phaseEvent.id), message: "unexpected active phase length")
}
@@ -251,7 +251,7 @@ access(all) fun mintDrop(
): [UInt64] {
txExecutor("drops/mint.cdc", [minter], [
nftTypeIdentifier, numToMint, totalCost, paymentIdentifier, paymentStoragePath, paymentReceiverPath, dropID, dropPhaseIndex, nftIdentifier, commissionAddress
], nil, nil)
])

let ids: [UInt64] = []
let events = Test.eventsOfType(Type<FlowtyDrops.Minted>())
14 changes: 7 additions & 7 deletions tests/test_helpers.cdc
Original file line number Diff line number Diff line change
@@ -35,7 +35,7 @@ access(all) fun expectScriptFailure(_ scriptName: String, _ arguments: [AnyStruc
return scriptResult.error!.message
}

access(all) fun txExecutor(_ txName: String, _ signers: [Test.TestAccount], _ arguments: [AnyStruct], _ expectedError: String?, _ expectedErrorType: ErrorType?): Test.TransactionResult {
access(all) fun txExecutor(_ txName: String, _ signers: [Test.TestAccount], _ arguments: [AnyStruct]): Test.TransactionResult {
let txCode = loadCode(txName, "transactions")

let authorizers: [Address] = []
@@ -173,7 +173,7 @@ access(all) fun deploy(_ name: String, _ path: String, _ arguments: [AnyStruct])
}

access(all) fun heartbeat() {
txExecutor("util/heartbeat.cdc", [serviceAccount], [], nil, nil)
txExecutor("util/heartbeat.cdc", [serviceAccount], [])
}

access(all) fun getCurrentTime(): UFix64 {
@@ -205,7 +205,7 @@ access(all) fun mintFromDrop(
nftIdentifier,
commissionReceiver
]
txExecutor("drops/mint.cdc", [minter], args, nil, nil)
txExecutor("drops/mint.cdc", [minter], args)
}

access(all) fun getDropIDs(
@@ -227,7 +227,7 @@ access(all) fun createEndlessOpenEditionDrop(
): UInt64 {
txExecutor("drops/add_endless_open_edition.cdc", [acct], [
name, description, ipfsCid, ipfsPath, price, paymentIdentifier, minterControllerID, nftTypeIdentifier
], nil, nil)
])

let e = Test.eventsOfType(Type<FlowtyDrops.DropAdded>()).removeLast() as! FlowtyDrops.DropAdded
return e.id
@@ -248,18 +248,18 @@ access(all) fun createTimebasedOpenEditionDrop(
): UInt64 {
txExecutor("drops/add_time_based_open_edition.cdc", [acct], [
name, description, ipfsCid, ipfsPath, price, paymentIdentifier, startUnix, endUnix, minterControllerID, nftTypeIdentifier
], nil, nil)
])

let e = Test.eventsOfType(Type<FlowtyDrops.DropAdded>()).removeLast() as! FlowtyDrops.DropAdded
return e.id
}

access(all) fun sendFlowTokens(fromAccount: Test.TestAccount, toAccount: Test.TestAccount, amount: UFix64) {
txExecutor("util/send_flow_tokens.cdc", [fromAccount], [toAccount.address, amount], nil, nil)
txExecutor("util/send_flow_tokens.cdc", [fromAccount], [toAccount.address, amount])
}

access(all) fun mintFlowTokens(_ acct: Test.TestAccount, _ amount: UFix64) {
txExecutor("flow-token/mint.cdc", [serviceAccount], [acct.address, amount], nil, nil)
txExecutor("flow-token/mint.cdc", [serviceAccount], [acct.address, amount])
}

access(all) fun flowTokenIdentifier(): String {