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

Update creators error: Incorrect account owner #261

Closed
elliott-w opened this issue Aug 28, 2022 · 14 comments
Closed

Update creators error: Incorrect account owner #261

elliott-w opened this issue Aug 28, 2022 · 14 comments
Labels
question Usage questions (redirecting to SO)

Comments

@elliott-w
Copy link

elliott-w commented Aug 28, 2022

I'mn trying to update a list of nfts to have a new secondary creator (the one with the 100% share). I don't think it's possible to update the first creator because I think the first creator is signed by the candy machine that created the nft? Anyway here's my code:

import { keypairIdentity, Metadata, Metaplex } from '@metaplex-foundation/js'
import { Connection, Keypair, PublicKey } from '@solana/web3.js'
import { program } from 'commander'
import { readFileSync, writeFileSync } from 'fs'

program
  .command('update_creators')
  .description('Updates the creator of all nfts')
  .requiredOption(
    '-i, --input-file <string>',
    'Json file, list of NFT mint details'
  )
  .requiredOption(
    '-o,  --output-file <string>',
    'Output file for NFT addresses that failed to update'
  )
  .requiredOption(
    '-k, --keypair-file <path>',
    `JSON file containing private key of token owner`,
    '.cache/creator-keypair.json'
  )
  .option('-r, --rpc <string>', 'JSON rpc api url', defaultRpc)
  .action(async ({ inputFile, outputFile, keypairFile, rpc }) => {
    const connection = new Connection(rpc)
    const metaplex = Metaplex.make(connection)
    const keypairFileContents = readFileSync(keypairFile, 'utf-8')
    const keypair = Keypair.fromSecretKey(
      Buffer.from(JSON.parse(keypairFileContents))
    )
    metaplex.use(keypairIdentity(keypair))

    const nftMintAddresses = JSON.parse(
      readFileSync(inputFile, 'utf-8')
    ) as string[]

    let nfts = (await metaplex
      .nfts()
      .findAllByMintList({
        mints: nftMintAddresses.map(mint => new PublicKey(mint)),
      })
      .run()) as Metadata[]

    const newCreator = new PublicKey(
      'CUAwUE5N3TdHHHyPTHb3E5mpnpQFiRF6BcY8kEvJakfS'
    )
    const failedNfts: any[] = []

    for (const nft of nfts) {
      try {
        console.dir(nft, { depth: null })
        const newNft = await metaplex
          .nfts()
          .update({
            nftOrSft: nft,
            creators: [
              nft.creators[0],
              {
                address: newCreator,
                share: 100,
                authority: keypair,
              },
            ],
          })
          .run()
        console.dir(newNft, { depth: null })
      } catch (e) {
        console.error(e)
        failedNfts.push(nft)
        process.exit()
      }
    }
    writeFileSync(outputFile, JSON.stringify(failedNfts))
  })

Note, the metaplex.use() keypair I'm using is the same wallet used to create the candy machine and has authority to update the nfts. I keep getting the following error:

ParsedProgramError [MetaplexError]: TokenMetadataProgram > Incorrect account owner
>> Source: Program > TokenMetadataProgram [metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s]
>> Problem: The program [TokenMetadataProgram] at address [metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s] raised an error of code [57] that translates to "Incorrect account owner".
>> Solution: Check the error message provided by the program.

Caused By: IncorrectOwner: Incorrect account owner

    at RpcClient.parseProgramError (C:\xampp\htdocs\sol-tools\node_modules\@metaplex-foundation\js\src\plugins\rpcModule\RpcClient.ts:302:9)
    at RpcClient.sendTransaction (C:\xampp\htdocs\sol-tools\node_modules\@metaplex-foundation\js\src\plugins\rpcModule\RpcClient.ts:87:18)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at async RpcClient.sendAndConfirmTransaction (C:\xampp\htdocs\sol-tools\node_modules\@metaplex-foundation\js\src\plugins\rpcModule\RpcClient.ts:117:23)
    at async TransactionBuilder.sendAndConfirm (C:\xampp\htdocs\sol-tools\node_modules\@metaplex-foundation\js\src\utils\TransactionBuilder.ts:189:22)
    at async C:\xampp\htdocs\sol-tools\node_modules\@metaplex-foundation\js\src\utils\Task.ts:82:23
    at async Disposable.run (C:\xampp\htdocs\sol-tools\node_modules\@metaplex-foundation\js\src\utils\Disposable.ts:34:14)
    at async Command.<anonymous> (C:\xampp\htdocs\sol-tools\src\cli.ts:263:24) {
  key: 'metaplex.errors.program.parsed_program_error',
  title: 'TokenMetadataProgram > Incorrect account owner',
  problem: 'The program [TokenMetadataProgram] at address [metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s] raised an error of code [57] that translates to "Incorrect account owner".',
  solution: 'Check the error message provided by the program.',
  source: 'program',
  sourceDetails: 'TokenMetadataProgram [metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s]',
  cause: IncorrectOwner: Incorrect account owner
      at Object.errorResolver (C:\xampp\htdocs\sol-tools\node_modules\@metaplex-foundation\js\src\plugins\nftModule\plugin.ts:70:16)
      at RpcClient.parseProgramError (C:\xampp\htdocs\sol-tools\node_modules\@metaplex-foundation\js\src\plugins\rpcModule\RpcClient.ts:299:35)
      at RpcClient.sendTransaction (C:\xampp\htdocs\sol-tools\node_modules\@metaplex-foundation\js\src\plugins\rpcModule\RpcClient.ts:87:18)
      at processTicksAndRejections (node:internal/process/task_queues:96:5)
      at async RpcClient.sendAndConfirmTransaction (C:\xampp\htdocs\sol-tools\node_modules\@metaplex-foundation\js\src\plugins\rpcModule\RpcClient.ts:117:23)
      at async TransactionBuilder.sendAndConfirm (C:\xampp\htdocs\sol-tools\node_modules\@metaplex-foundation\js\src\utils\TransactionBuilder.ts:189:22)
      at async C:\xampp\htdocs\sol-tools\node_modules\@metaplex-foundation\js\src\utils\Task.ts:82:23
      at async Disposable.run (C:\xampp\htdocs\sol-tools\node_modules\@metaplex-foundation\js\src\utils\Disposable.ts:34:14)
      at async Command.<anonymous> (C:\xampp\htdocs\sol-tools\src\cli.ts:263:24) {
    code: 57
  },
  logs: undefined,
  program: {
    name: 'TokenMetadataProgram',
    address: PublicKey {
      _bn: <BN: b7065b1e3d17c45389d527f6b04c3cd58b86c731aa0fdb549b6d1bc03f82946>
    },
    errorResolver: [Function: errorResolver],
    gpaResolver: [Function: gpaResolver]
  }
}

And here's one of the NFTs I'm trying to update:

https://solscan.io/token/3woKb11Ajs9VkzHhMNkiyX5za1bV3STBmSaDHoQgmBKp#metadata

Any help would be appreciated. Thanks!

@lorisleiva
Copy link
Contributor

It looks like the Metadata account you're trying to update is not owned by the Token Metadata program.

See https://github.com/metaplex-foundation/metaplex-program-library/blob/58d10c46e66ca9d9c6288999ca9289c986587c7f/token-metadata/program/src/processor.rs#L326

Also, your update call is adding a new creator with 100% shares whilst the current creators[0] should also have 100% shares. Once you get past this error, the program will complain that your new creator array does not add up to 100%.

@elliott-w
Copy link
Author

@lorisleiva

It looks like the Metadata account you're trying to update is not owned by the Token Metadata program.

Is that normal for NFTs minted via CMv2?

@lorisleiva
Copy link
Contributor

No, NFTs minted via CMv2 should have the right owner on the Metadata account, unless it was a forked CMv2 program or something like that. Have you tried with another NFT to be sure?

@elliott-w
Copy link
Author

Unless it was a forked CMv2 program

No nothing like that, CM was made using the depecrated candy-machine-v2-cli.ts

Have you tried with another NFT to be sure?

Yeah here's another one from the same candy machine:
https://solscan.io/token/YAPp4X629HnHLnpRf4cEWhUFEeiSx3uJQhi95nu65Em#metadata

If I do:

const nftMintAddresses = ['YAPp4X629HnHLnpRf4cEWhUFEeiSx3uJQhi95nu65Em']

still gives same incorrect account owner error.

Also, your update call is adding a new creator

Could you please elaborate? I thought by specifying the creators property I'm replacing the old creators array with a new one?

@lorisleiva
Copy link
Contributor

Hmmm... I'm super confused. I've checked your NFTs and they seem to have the correct programs as owners (both the Token Metadata for the Metadata account and the SPL Token for the Mint and the Token accounts). So I'm not sure why you'd get incorrect account owner because that can only occur when you get an unexpected program owner for an account.

Which RPC and cluster are you using when running this update operation?

Could you please elaborate? I thought by specifying the creators property I'm replacing the old creators array with a new one?

Ignore me, I assumed the first creator already had 100% but I can see now it's got 0%. Sorry about that.

@elliott-w
Copy link
Author

I've messed up somewhere I'm sure of it 😅

Which RPC and cluster are you using when running this update operation?

mainnet-beta, I've tried both my quiknode:
https://autumn-wispy-forest.solana-mainnet.quiknode.pro/9df0b2e72ee22da25d7be7cc97fb85656e938255
And genesysgo:
https://ssc-dao.genesysgo.net/

@lorisleiva
Copy link
Contributor

Well, you seem to be doing everything properly so I'm not sure why you'd have this incorrect owner error.

I'll reopen this until we find out what's causing this issue.

@lorisleiva lorisleiva reopened this Aug 30, 2022
@elliott-w
Copy link
Author

Thanks, much appreciated

@elliott-w
Copy link
Author

@lorisleiva can you recommend another way to update creators at this point?

@lorisleiva
Copy link
Contributor

@elliott-w Sure, you can use the @metaplex-foundation/mpl-token-metadata library directly which is auto-generated from the Rust program. But the SDK delegates to that library so I'm not sure if that would make a difference.

@lorisleiva
Copy link
Contributor

Hi there 👋

I'm just going through all issues again today. and I was wondering if you'd find a solution to this issue.

I'm still confused as to why the update operation wouldn't work since what you're trying to achieve has been heavily tested on the SDK.

If you could provide a small repository for me to play with such that it's got the minimum amount of code required to reproduce the issue that'd be super helpful.

Thanks again for raising this.

@lorisleiva lorisleiva added the question Usage questions (redirecting to SO) label Sep 30, 2022
@lorisleiva
Copy link
Contributor

Closing this due to inactivity.

@sohrab-
Copy link

sohrab- commented Apr 26, 2023

I don't know if I should revive this old thread but I think I know what's going on here.

These find*() methods return Metadata but the update() method assumes that it is Sft or Nft only so it just plugs in the address field into the mint, and uses this to derive other stuff like metadata and edition, which most likely won't exist, and hence won't have the correct parent.

TypeScript doesn't complain because the type of UpdateNftInput.nftOrSft happens to be a superset of Metadata. That method should ideally do further checks to reject Metadata or alternatively cater for Metadata input.

The workaround is to convert Metadata into Sft/Nft using say metaplex.nfts().load() (it will make additional RPC calls).


Here is a minimal example:

const nfts = await metaplex.nfts().findAllByUpdateAuthority({
  updateAuthority: myAuthority.publicKey,
});
await metaplex
  .nfts()
  .update({
    nftOrSft: nfts[0],
    authority: myAuthority,
    newUpdateAuthority: myNewAuthority,
  })

Here is a devnet example:

"@metaplex-foundation/js": "^0.18.3",

@lpbonomi
Copy link

That worked for me! Thanks @sohrab-

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Usage questions (redirecting to SO)
Projects
None yet
Development

No branches or pull requests

4 participants