Skip to content

Commit

Permalink
fix find by cm logic, fix some unit tests (#82)
Browse files Browse the repository at this point in the history
  • Loading branch information
Funkatronics authored Nov 14, 2022
1 parent 4816e54 commit b3c2e9c
Show file tree
Hide file tree
Showing 5 changed files with 170 additions and 18 deletions.
7 changes: 6 additions & 1 deletion lib/src/main/java/com/metaplex/lib/modules/nfts/NftClient.kt
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class NftClient(private val connection: Connection, val signer: IdentityDriver,
FindNftsByCreatorOnChainOperationHandler(connection, dispatcher)
.handle(FindNftsByCreatorInput(creator, position))

suspend fun findAllByCandyMachine(candyMachine: PublicKey, version: UInt? = 2U): Result<List<NFT?>> =
suspend fun findAllByCandyMachine(candyMachine: PublicKey, version: Int? = 2): Result<List<NFT?>> =
FindNftsByCandyMachineOnChainOperationHandler(connection, dispatcher)
.handle(FindNftsByCandyMachineInput(candyMachine, version))
//endregion
Expand All @@ -65,4 +65,9 @@ class NftClient(private val connection: Connection, val signer: IdentityDriver,
return FindNftByMintOnChainOperationHandler(connection, dispatcher)
.handle(newMintAccount.publicKey)
}

@Deprecated("Deprecated, please use the signed integer version instead",
replaceWith = ReplaceWith("findAllByCandyMachine(candyMachine, version)"))
suspend fun findAllByCandyMachine(candyMachine: PublicKey, version: UInt? = 2U)
: Result<List<NFT?>> = findAllByCandyMachine(candyMachine, version?.toInt())
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package com.metaplex.lib.modules.nfts.operations

import com.metaplex.lib.Metaplex
import com.metaplex.lib.drivers.solana.Connection
import com.metaplex.lib.modules.candymachines.models.CandyMachine
import com.metaplex.lib.modules.candymachinesv2.models.CandyMachineV2
import com.metaplex.lib.modules.nfts.models.NFT
import com.metaplex.lib.shared.*
import com.solana.core.PublicKey
Expand All @@ -10,27 +12,26 @@ import kotlinx.coroutines.Dispatchers

data class FindNftsByCandyMachineInput(
val candyMachine : PublicKey,
val version : UInt?,
val version : Int?,
)

val candyMachineId = PublicKey("cndy3Z4yapfJBmL3ShUp5exZKqR3z33thTzeNMm2gRZ")
class FindNftsByCandyMachineOnChainOperationHandler(override val connection: Connection,
override val dispatcher: CoroutineDispatcher = Dispatchers.IO)
: OperationHandler<FindNftsByCandyMachineInput, List<NFT?>> {

constructor(metaplex: Metaplex) : this(metaplex.connection)

override suspend fun handle(input: FindNftsByCandyMachineInput): Result<List<NFT?>> {
val cmAddress = if((input.version ?: 2) == 2){
val pdaSeeds = listOf(
val cmAddress = if(input.version == 3){
PublicKey.findProgramAddress(listOf(
"candy_machine".toByteArray(),
candyMachineId.toByteArray(),
)
val pdaAddres = PublicKey.findProgramAddress(
pdaSeeds,
candyMachineId
)
pdaAddres.address
input.candyMachine.toByteArray(),
), PublicKey(CandyMachine.PROGRAM_ADDRESS)).address
} else if(input.version == 2){
PublicKey.findProgramAddress(listOf(
CandyMachineV2.PROGRAM_NAME.toByteArray(),
input.candyMachine.toByteArray()
), PublicKey(CandyMachineV2.PROGRAM_ADDRESS)).address
} else input.candyMachine

return FindNftsByCreatorOnChainOperationHandler(connection, dispatcher)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -278,15 +278,17 @@ class CandyMachineClientTests {
// when
connection.airdrop(signer.publicKey, 1f)
val nft = createCollectionNft(connection, identityDriver).getOrThrow()
val mintResult = client.create(250, 1, nft.mint, signer.publicKey).map {
val mintResult = client.create(250, 1, nft.mint,
signer.publicKey, withoutCandyGuard = true).map {
client.insertItems(it, listOf(
CandyMachineItem("My NFT", "https://example.com/mynft"),
))
client.mintNft(it)//.getOrThrow()
client.mintNft(it).getOrThrow()
}.getOrThrow()

// then
Assert.assertNotNull(mintResult)
Assert.assertEquals(nft.mint, mintResult.collection?.key)
}

//region CANDY GUARDS
Expand Down Expand Up @@ -452,15 +454,18 @@ class CandyMachineClientTests {
// when
connection.airdrop(signer.publicKey, 10f)
val nft = createCollectionNft(connection, identityDriver).getOrThrow()
val candyMachine = client.create(333, 5000, nft.mint, signer.publicKey).getOrThrow()
val candyMachine = client.create(333, 5000, nft.mint,
signer.publicKey, withoutCandyGuard = true).getOrThrow()
val candyGuard = client.createCandyGuard(listOf(), mapOf()).getOrThrow()

client.wrapCandyGuard(candyGuard, candyMachine.address)

val finalCandyMachine = client.refresh(candyMachine)
val finalCandyMachine = client.refresh(candyMachine).getOrThrow()

//then
Assert.assertNotNull(finalCandyMachine)
Assert.assertEquals(candyGuard.authority, finalCandyMachine.authority)
Assert.assertEquals(CandyGuard.pda(candyGuard.base).address, finalCandyMachine.mintAuthority)
}

@Test
Expand All @@ -475,15 +480,18 @@ class CandyMachineClientTests {
// when
connection.airdrop(signer.publicKey, 10f)
val nft = createCollectionNft(connection, identityDriver).getOrThrow()
val candyMachine = client.create(333, 5000, nft.mint, signer.publicKey, authority.publicKey).getOrThrow()
val candyMachine = client.create(333, 5000, nft.mint,
signer.publicKey, authority.publicKey, withoutCandyGuard = true).getOrThrow()
val candyGuard = client.createCandyGuard(listOf(), mapOf(), authority.publicKey).getOrThrow()

client.wrapCandyGuard(candyGuard, candyMachine.address, authority)

val finalCandyMachine = client.refresh(candyMachine)
val finalCandyMachine = client.refresh(candyMachine).getOrThrow()

//then
Assert.assertNotNull(finalCandyMachine)
Assert.assertEquals(candyGuard.authority, finalCandyMachine.authority)
Assert.assertEquals(CandyGuard.pda(candyGuard.base).address, finalCandyMachine.mintAuthority)
}
//endregion
//endregion
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
/*
* FindNftsByCandyMachineOperationHnadlerTests
* Metaplex
*
* Created by Funkatronics on 11/14/2022
*/

package com.metaplex.lib.modules.nfts.operations

import com.metaplex.lib.MetaplexTestUtils
import com.metaplex.lib.drivers.solana.SolanaConnectionDriver
import com.metaplex.lib.generateConnectionDriver
import com.metaplex.lib.generateMetaplexInstance
import com.metaplex.lib.modules.candymachines.models.CandyMachineItem
import com.metaplex.lib.modules.nfts.models.Metadata
import com.metaplex.lib.modules.nfts.models.NFT
import com.metaplex.lib.shared.OperationError
import com.metaplex.mock.driver.rpc.MockErrorRpcDriver
import com.solana.core.HotAccount
import com.solana.core.PublicKey
import com.util.airdrop
import kotlinx.coroutines.test.runTest
import org.junit.Assert
import org.junit.Test

class FindNftsByCandyMachineOperationHandlerTests {

@Test
fun testFindAllByOwnerHandlesAndReturnsError() = runTest {
// given
val expectedErrorMessage = "An Error Occurred"
val owner = PublicKey(ByteArray(PublicKey.PUBLIC_KEY_LENGTH))
val connection = SolanaConnectionDriver(MockErrorRpcDriver(expectedErrorMessage))

// when
val result = FindNftsByCandyMachineOnChainOperationHandler(connection)
.handle(FindNftsByCandyMachineInput(owner, 3))

// This is really bad, OperationError needs to be refactored. An exception should not wrap
// another exception into a custom property. Getting the actual error out is so gross:
val actualExceptionUnwrapped =
(result.exceptionOrNull() as? OperationError.GetFindNftsByCreatorOperation)?.exception

// then
Assert.assertTrue(result.isFailure)
Assert.assertEquals(expectedErrorMessage, actualExceptionUnwrapped?.message)
}
//endregion

@Test
fun testFindNftsByCandyMachineV2OnChainOperation() = runTest {
// given
val owner = HotAccount()
val connection = MetaplexTestUtils.generateConnectionDriver()
val metaplex = MetaplexTestUtils.generateMetaplexInstance(owner, connection)

// when
connection.airdrop(owner.publicKey, 1f)

val candyMachine =
metaplex.candyMachinesV2.create(1, 250, 1).getOrThrow()

val createdNft = metaplex.candyMachinesV2.mintNft(candyMachine).getOrThrow()

val ownerNfts: List<NFT?> = FindNftsByCandyMachineOnChainOperationHandler(connection)
.handle(FindNftsByCandyMachineInput(candyMachine.address, 2)).getOrThrow()

// then
Assert.assertNotNull(ownerNfts.first())
Assert.assertTrue(ownerNfts.size == 1)
Assert.assertEquals(createdNft.mint, ownerNfts.first()?.mint)
Assert.assertEquals(createdNft.metadataAccount.mint,
ownerNfts.first()?.metadataAccount?.mint)
Assert.assertEquals(createdNft.metadataAccount.update_authority,
ownerNfts.first()?.metadataAccount?.update_authority)
}

@Test
fun testFindNftsByCandyMachineOnChainOperation() = runTest {
// given
val owner = HotAccount()
val connection = MetaplexTestUtils.generateConnectionDriver()
val metaplex = MetaplexTestUtils.generateMetaplexInstance(owner, connection)

// when
connection.airdrop(owner.publicKey, 1f)

val collection = metaplex.nft.create(
Metadata("My NFT", uri = "http://example.com/sd8756fsuyvvbf37684",
sellerFeeBasisPoints = 250), true
).getOrThrow()

val candyMachine = metaplex.candyMachines.create(250, 1,
collection.mint, collection.updateAuthority, withoutCandyGuard = true).getOrThrow()

metaplex.candyMachines.insertItems(candyMachine,
listOf(CandyMachineItem("Degen #1", "https://example.com/degen/1")))

val createdNft = metaplex.candyMachines.mintNft(candyMachine).getOrThrow()

val ownerNfts: List<NFT?> = FindNftsByCandyMachineOnChainOperationHandler(connection)
.handle(FindNftsByCandyMachineInput(candyMachine.address, 3)).getOrThrow()

// then
Assert.assertNotNull(ownerNfts.first())
Assert.assertTrue(ownerNfts.size == 1)
Assert.assertEquals(createdNft.mint, ownerNfts.first()?.mint)
Assert.assertEquals(createdNft.metadataAccount.mint,
ownerNfts.first()?.metadataAccount?.mint)
Assert.assertEquals(createdNft.metadataAccount.update_authority,
ownerNfts.first()?.metadataAccount?.update_authority)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,13 @@
package com.metaplex.lib.modules.nfts.operations

import com.metaplex.lib.*
import com.metaplex.lib.drivers.solana.SolanaConnectionDriver
import com.metaplex.lib.modules.nfts.models.Metadata
import com.metaplex.lib.modules.nfts.models.NFT
import com.metaplex.lib.shared.OperationError
import com.metaplex.mock.driver.rpc.MockErrorRpcDriver
import com.solana.core.HotAccount
import com.solana.core.PublicKey
import com.util.airdrop
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest
Expand All @@ -14,6 +18,27 @@ import org.junit.Test

class FindNftsByOwnerOnChainOperationHandlerTests {

@Test
fun testFindAllByOwnerHandlesAndReturnsError() = runTest {
// given
val expectedErrorMessage = "An Error Occurred"
val owner = PublicKey(ByteArray(PublicKey.PUBLIC_KEY_LENGTH))
val connection = SolanaConnectionDriver(MockErrorRpcDriver(expectedErrorMessage))

// when
val result = FindNftsByOwnerOnChainOperationHandler(connection).handle(owner)

// This is really bad, OperationError needs to be refactored. An exception should not wrap
// another exception into a custom property. Getting the actual error out is so gross:
val actualExceptionUnwrapped =
(result.exceptionOrNull() as? OperationError.GetFindNftsByOwnerOperation)?.exception

// then
Assert.assertTrue(result.isFailure)
Assert.assertEquals(expectedErrorMessage, actualExceptionUnwrapped?.message)
}
//endregion

@Test
fun testFindNftsByOwnerOnChainOperation() = runTest {
// given
Expand Down

0 comments on commit b3c2e9c

Please sign in to comment.