Skip to content
Open
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
8 changes: 5 additions & 3 deletions components/SendNft.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -146,21 +146,23 @@ const SendNft = ({
const fromOwner = tryParseKey(fromOwnerString)
// should be impossible, but stuff isn't typed
if (fromOwner === null) throw new Error()

const transferIx = await createIx_transferNft(
connection,
fromOwner,
toOwner,
nftMint,
nft,
fromOwner,
nativeTreasury,
)

if (!transferIx) throw new Error('failed to create transfer instruction');

return {
serializedInstruction: serializeInstructionToBase64(transferIx),
isValid: true,
prerequisiteInstructions:
destinationAtaQueried === null
destinationAtaQueried === null && nft.interface !== 'MplCoreAsset'
? [
Token.createAssociatedTokenAccountInstruction(
ASSOCIATED_TOKEN_PROGRAM_ID, // always ASSOCIATED_TOKEN_PROGRAM_ID
Expand Down
1 change: 1 addition & 0 deletions hooks/queries/digitalAssets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ export type DasNftObject = {
verified: boolean
}[]
id: string
interface?: string
}

/*** Here is an example item from the DAS Api, since it's not typed and the docs dont give the full schema.
Expand Down
4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,11 @@
"@mean-dao/payment-streaming": "4.0.3",
"@metaplex-foundation/beet": "0.7.2",
"@metaplex-foundation/js": "0.19.4",
"@metaplex-foundation/mpl-core": "1.7.0",
"@metaplex-foundation/mpl-token-metadata": "2.10.0",
"@metaplex-foundation/umi": "1.4.1",
"@metaplex-foundation/umi-bundle-defaults": "1.4.1",
"@metaplex-foundation/umi-web3js-adapters": "1.4.1",
"@multifarm/solana-realms": "1.0.6",
"@next/bundle-analyzer": "12.1.5",
"@nivo/bar": "0.79.1",
Expand Down
74 changes: 52 additions & 22 deletions utils/metaplex.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
import { DasNftObject } from '@hooks/queries/digitalAssets'
import { fetchNFTbyMint } from '@hooks/queries/nft'
import { Metaplex } from '@metaplex-foundation/js'
import { Connection, PublicKey } from '@solana/web3.js'
import { transferV1 } from "@metaplex-foundation/mpl-core"
import { createUmi } from '@metaplex-foundation/umi-bundle-defaults'
import { generateSigner, publicKey, signerIdentity, signerPayer } from '@metaplex-foundation/umi'
import { toWeb3JsInstruction } from '@metaplex-foundation/umi-web3js-adapters'

export const createIx_transferNft = async (
connection: Connection,
fromOwner: PublicKey,
toOwner: PublicKey,
mint: PublicKey,
nft: DasNftObject,
authority: PublicKey,
payer: PublicKey,
payer: PublicKey
) => {
const metaplex = new Metaplex(
connection,
Expand All @@ -21,27 +26,52 @@ export const createIx_transferNft = async (
//metaplex.identity = () => ({ publicKey: fromOwner } as any) // you need to do this to set payer and authority. I love OOP!!
// except the payer might not be the same person. great!

const nft = await fetchNFTbyMint(connection, mint)
if (!nft.result) throw 'failed to fetch nft'
const mint = new PublicKey(nft.id);
const umi = createUmi(connection.rpcEndpoint)
const signer = generateSigner(umi);
umi.use(signerIdentity(signer));

const tokenStandard = nft.result.tokenStandard
const ruleSet = nft.result.programmableConfig?.ruleSet
try {
const nft = await fetchNFTbyMint(connection, mint)
if (!nft.result) throw 'failed to fetch nft'

const ix = metaplex
.nfts()
.builders()
.transfer({
nftOrSft: {
address: mint,
tokenStandard,
},
authorizationDetails: ruleSet ? { rules: ruleSet } : undefined,
toOwner,
fromOwner,
})
.getInstructions()[0]
const tokenStandard = nft.result.tokenStandard
const ruleSet = nft.result.programmableConfig?.ruleSet

ix.keys[9].pubkey = authority
ix.keys[10].pubkey = payer
return ix
const ix = metaplex
.nfts()
.builders()
.transfer({
nftOrSft: {
address: mint,
tokenStandard,
},
authorizationDetails: ruleSet ? { rules: ruleSet } : undefined,
toOwner,
fromOwner,
})
.getInstructions()[0]

ix.keys[9].pubkey = authority
ix.keys[10].pubkey = payer
return ix
} catch(error) {
if (nft.interface === 'MplCoreAsset') {
// fallback for mpl core assets
const ixMpl = transferV1(umi, {
asset: publicKey(nft.id),
newOwner: publicKey(toOwner),
collection: nft.grouping.some((g) => g.group_key === 'collection')
? publicKey(
nft.grouping.find((g) => g.group_key === 'collection')!.group_value
) : undefined,
})

const ix = toWeb3JsInstruction(ixMpl.items[0].instruction);
ix.keys[2].pubkey = fromOwner;
return ix;
} else {
throw new Error('failed to create transfer instruction')
}
}
}