import NinaClient from '../client';
import * as anchor from '@project-serum/anchor';
import {
findOrCreateAssociatedTokenAccount,
getUsdcBalance,
createMintInstructions,
uiToNative,
decodeNonEncryptedByteArray,
getConfirmTransaction,
TOKEN_PROGRAM_ID,
} from '../utils';
import Hub from './hubs';
import axios from 'axios';
/**
* @module Release
*/
const MAX_INT = '18446744073709551615';
/**
* @function fetchAll
* Fetches all releases.
* @param {Object} [pagination = {limit: 20, offset: 0, sort: 'desc'}] Pagination options.
* @param {Boolean} [withAccountData = false] Fetch full on-chain Release accounts.
* @example const releases = await NinaClient.Release.fetchAll();
*/
const fetchAll = async (pagination = {}, withAccountData = false) => {
const { limit, offset, sort } = pagination;
return await NinaClient.get(
'/releases',
{
limit: limit || 20,
offset: offset || 0,
sort: sort || 'desc',
},
withAccountData
);
};
/**
* @function fetch
* @param {String} publicKey The public key of the release.
* @param {Boolean} [withAccountData = false] Fetch full on-chain Release account.
* @example const release = await NinaClient.Release.fetch("4dS4v5dGrUwEZmjCFu56qgyAmRfaPmns9PveWAw61rEQ");
*/
const fetch = async (publicKey, withAccountData = false) => {
return await NinaClient.get(`/releases/${publicKey}`, undefined, withAccountData);
};
/**
* @function fetchCollectors
* @param {String} publicKey The public key of the release.
* @param {Boolean} [withCollection = false] Fetch collectors collections.
* @param {Object} [pagination = {limit, offset, sort}] Pagination options.
* @example const collectors = await NinaClient.Release.fetchCollectors("4dS4v5dGrUwEZmjCFu56qgyAmRfaPmns9PveWAw61rEQ");
*/
const fetchCollectors = async (publicKey, withCollection = false) => {
return await NinaClient.get(`/releases/${publicKey}/collectors${withCollection ? '?withCollection=true' : ''}`);
};
/**
* @function fetchHubs
* @param {String} publicKey The public key of the release.
* @param {Boolean} [withAccountData = false] Fetch full on-chain Hub and HubRelease accounts.
* @param {Object} [pagination = {limit, offset, sort}] Pagination options.
* @example const hubs = await NinaClient.Release.fetchHubs("4dS4v5dGrUwEZmjCFu56qgyAmRfaPmns9PveWAw61rEQ");
*/
const fetchHubs = async (publicKey, withAccountData = false) => {
return await NinaClient.get(`/releases/${publicKey}/hubs`, undefined, withAccountData);
};
/**
* @function fetchExchanges
* @param {String} publicKey The public key of the release.
* @param {Boolean} [withAccountData = false] Fetch full on-chain Exchange accounts.
* @param {Object} [pagination = {limit, offset, sort}] Pagination options.
* @example const exchanges = await NinaClient.Release.fetchExchanges("4dS4v5dGrUwEZmjCFu56qgyAmRfaPmns9PveWAw61rEQ");
*/
const fetchExchanges = async (publicKey, withAccountData = false, pagination) => {
return await NinaClient.get(`/releases/${publicKey}/exchanges`, pagination, withAccountData);
};
/**
* @function fetchRevenueShareRecipients
* @param {String} publicKey The public key of the release.
* @param {Boolean} [withAccountData = false] Fetch full on-chain Release accounts.
* @param {Object} [pagination = {limit, offset, sort}] Pagination options.
* @example const revenueShareRecipients = await NinaClient.Release.fetchRevenueShareRecipients("4dS4v5dGrUwEZmjCFu56qgyAmRfaPmns9PveWAw61rEQ");
*/
const fetchRevenueShareRecipients = async (publicKey, withAccountData = false) => {
return await NinaClient.get(`/releases/${publicKey}/revenueShareRecipients`, undefined, withAccountData);
};
/**
*
* @function purchaseViaHub
* @param {Object} client NinaClient instance.
* @param {String} releasePublicKey Public Key of the release.
* @param {String} hubPublicKey Public Key of the hub.
* @example const transactionId = await NinaClient.Release.purchaseViaHub(client, "4dS4v5dGrUwEZmjCFu56qgyAmRfaPmns9PveWAw61rEQ", "4dS4v5dGrUwEZmjCFu56qgyAmRfaPmns9PveWAw61rEQ");
* @returns {String} the transaction ID.
*/
const purchaseViaHub = async (client, releasePublicKey, hubPublicKey) => {
try {
const { provider } = client;
const program = await client.useProgram();
releasePublicKey = new anchor.web3.PublicKey(releasePublicKey);
hubPublicKey = new anchor.web3.PublicKey(hubPublicKey);
const release = await program.account.release.fetch(releasePublicKey);
let [payerTokenAccount] = await findOrCreateAssociatedTokenAccount(
provider.connection,
provider.wallet.publicKey,
provider.wallet.publicKey,
anchor.web3.SystemProgram.programId,
anchor.web3.SYSVAR_RENT_PUBKEY,
release.paymentMint
);
let [receiverReleaseTokenAccount, receiverReleaseTokenAccountIx] = await findOrCreateAssociatedTokenAccount(
provider.connection,
provider.wallet.publicKey,
provider.wallet.publicKey,
anchor.web3.SystemProgram.programId,
anchor.web3.SYSVAR_RENT_PUBKEY,
release.releaseMint
);
const hub = await program.account.hub.fetch(hubPublicKey);
const [hubRelease] = await anchor.web3.PublicKey.findProgramAddress(
[
Buffer.from(anchor.utils.bytes.utf8.encode('nina-hub-release')),
hubPublicKey.toBuffer(),
releasePublicKey.toBuffer(),
],
program.programId
);
const [hubContent] = await anchor.web3.PublicKey.findProgramAddress(
[
Buffer.from(anchor.utils.bytes.utf8.encode('nina-hub-content')),
hubPublicKey.toBuffer(),
releasePublicKey.toBuffer(),
],
program.programId
);
const [hubSigner] = await anchor.web3.PublicKey.findProgramAddress(
[Buffer.from(anchor.utils.bytes.utf8.encode('nina-hub-signer')), hubPublicKey.toBuffer()],
program.programId
);
let [hubWallet] = await findOrCreateAssociatedTokenAccount(
provider.connection,
provider.wallet.publicKey,
hubSigner,
anchor.web3.SystemProgram.programId,
anchor.web3.SYSVAR_RENT_PUBKEY,
release.paymentMint
);
const instructions = [];
const solPrice = await axios.get(`https://price.jup.ag/v1/price?id=SOL`);
let releasePriceUi = release.price.toNumber() / Math.pow(10, 6);
let convertAmount = releasePriceUi + (releasePriceUi * hub.referralFee.toNumber()) / 1000000;
let usdcBalance = await getUsdcBalance(provider.wallet.publicKey, provider.connection);
if (usdcBalance < convertAmount) {
const additionalComputeBudgetInstruction = anchor.web3.ComputeBudgetProgram.requestUnits({
units: 400000,
additionalFee: 0,
});
instructions.push(additionalComputeBudgetInstruction);
convertAmount -= usdcBalance;
const amt = Math.round(((convertAmount + convertAmount * 0.01) / solPrice.data.data.price) * Math.pow(10, 9));
const { data } = await axios.get(
`https://quote-api.jup.ag/v1/quote?inputMint=So11111111111111111111111111111111111111112&outputMint=EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v&amount=${amt}&slippage=0.5&onlyDirectRoutes=true`
);
let transactionInstructions;
for await (let d of data.data) {
const transactions = await axios.post('https://quote-api.jup.ag/v1/swap', {
route: d,
userPublicKey: provider.wallet.publicKey.toBase58(),
});
if (!transactionInstructions) {
transactionInstructions = anchor.web3.Transaction.from(
Buffer.from(transactions.data.swapTransaction, 'base64')
).instructions;
} else {
const tx = anchor.web3.Transaction.from(Buffer.from(transactions.data.swapTransaction, 'base64'));
let accountCount = tx.instructions.reduce((count, ix) => (count += ix.keys.length), 0);
if (accountCount < transactionInstructions.reduce((count, ix) => (count += ix.keys.length), 0)) {
transactionInstructions = tx.instructions;
}
}
}
instructions.push(...transactionInstructions);
}
if (receiverReleaseTokenAccountIx) {
instructions.push(receiverReleaseTokenAccountIx);
}
if (instructions.length > 0) {
request.instructions = instructions;
}
const tx = await program.methods
.releasePurchaseViaHub(release.price, decodeNonEncryptedByteArray(hub.handle))
.accounts({
payer: provider.wallet.publicKey,
receiver: provider.wallet.publicKey,
release: releasePublicKey,
releaseSigner: release.releaseSigner,
payerTokenAccount,
receiverReleaseTokenAccount,
royaltyTokenAccount: release.royaltyTokenAccount,
releaseMint: release.releaseMint,
hub: hubPublicKey,
hubRelease,
hubContent,
hubSigner,
hubWallet,
tokenProgram: anchor.utils.token.TOKEN_PROGRAM_ID,
})
.preInstructions(instructions || [])
.transaction();
tx.recentBlockhash = (await provider.connection.getRecentBlockhash()).blockhash;
tx.feePayer = provider.wallet.publicKey;
const txid = await provider.wallet.sendTransaction(tx, provider.connection);
await getConfirmTransaction(txid, provider.connection);
return txid;
} catch (error) {
console.warn(error);
return false;
}
};
/**
*
* @function releasePurchase
* @param {Object} client NinaClient instance.
* @param {String} releasePublicKey Public Key of the release.
* @param {String} hubPublicKey Public Key of the hub.
* @returns {String} Transaction Id.
*/
const releasePurchase = async (client, releasePublicKey) => {
try {
const { provider } = client;
const program = await client.useProgram();
releasePublicKey = new anchor.web3.PublicKey(releasePublicKey);
const release = await program.account.release.fetch(releasePublicKey);
if (release.price.toNumber === 0) {
const message = new TextEncoder().encode(releasePublicKey.toBase58());
const messageBase64 = encodeBase64(message);
const signature = await provider.wallet.sign(message);
const signatureBase64 = encodeBase64(signature);
const response = await axios.get(
`${process.env.NINA_IDENTITY_ENDPOINT}/collect/${releasePublicKey.toBase58()}?message=${encodeURIComponent(
messageBase64
)}&signature=${encodeURIComponent(signatureBase64)}&publicKey=${encodeURIComponent(
provider.wallet.publicKey.toBase58()
)}`
);
return response.data.txid;
}
let [payerTokenAccount] = await findOrCreateAssociatedTokenAccount(
provider.connection,
provider.wallet.publicKey,
provider.wallet.publicKey,
anchor.web3.SystemProgram.programId,
anchor.web3.SYSVAR_RENT_PUBKEY,
release.paymentMint
);
let [receiverReleaseTokenAccount, receiverReleaseTokenAccountIx] = await findOrCreateAssociatedTokenAccount(
provider.connection,
provider.wallet.publicKey,
provider.wallet.publicKey,
anchor.web3.SystemProgram.programId,
anchor.web3.SYSVAR_RENT_PUBKEY,
release.releaseMint
);
const instructions = [];
if (receiverReleaseTokenAccountIx) {
instructions.push({
instructions: [receiverReleaseTokenAccountIx],
cleanupInstructions: [],
signers: [],
});
}
if (client.isSol(release.paymentMint)) {
const [wrappedSolAccount, wrappedSolInstructions] = await wrapSol(provider, release.price, release.paymentMint);
if (!request.instructions) {
instructions = [...wrappedSolInstructions];
} else {
instructions.push(...wrappedSolInstructions);
}
payerTokenAccount = wrappedSolAccount;
}
const tx = await program.methods
.releasePurchase(release.price)
.accounts({
payer: provider.wallet.publicKey,
receiver: provider.wallet.publicKey,
release: releasePublicKey,
releaseSigner: release.releaseSigner,
payerTokenAccount,
receiverReleaseTokenAccount,
royaltyTokenAccount: release.royaltyTokenAccount,
releaseMint: release.releaseMint,
tokenProgram: TOKEN_PROGRAM_ID,
})
.preInstructions(instructions || [])
.transaction();
tx.recentBlockhash = (await provider.connection.getRecentBlockhash()).blockhash;
tx.feePayer = provider.wallet.publicKey;
const txid = await provider.wallet.sendTransaction(tx, provider.connection);
await getConfirmTransaction(txid, provider.connection);
return txid;
} catch (error) {
console.warn(error);
return false;
}
};
/**
*
* @function releaseInitViaHub
* @param {Object} client the NinaClient
* @param {String} hubPublicKey Public Key of the hub.
* @param {Number} retailPrice Retail price of the release.
* @param {Number} amount Amount of the release.
* @param {Number} resalePercentage Resale percentage of the release.
* @param {Boolean} isUsdc Is the payment in USDC or SOL.
* @param {String} metadataUri Metadata URI of the release.
* @param {String} artist Artist of the release.
* @param {String} title Title of the release.
* @param {String} catalogNumber Catalog number of the release.
* @param {String} release Release of the release.
* @param {String} releaseBump Release bump of the release.
* @param {String} releaseMint Release mint of the release.
* @param {Boolean} isOpen Is the release open or not.
* @returns {Object} The release.
*/
const releaseInitViaHub = async (
client,
hubPubkey,
retailPrice,
amount,
resalePercentage,
isUsdc = true,
metadataUri,
artist,
title,
catalogNumber,
release,
releaseBump,
releaseMint,
isOpen
) => {
try {
const ids = NinaClient.ids;
const { provider } = client;
const program = await client.useProgram();
hubPubkey = new anchor.web3.PublicKey(hubPubkey);
const hub = await program.account.hub.fetch(hubPubkey);
const paymentMint = new anchor.web3.PublicKey(isUsdc ? ids.mints.usdc : ids.mints.wsol);
const [releaseSigner, releaseSignerBump] = await anchor.web3.PublicKey.findProgramAddress(
[release.toBuffer()],
program.programId
);
const releaseMintIx = await createMintInstructions(provider, provider.wallet.publicKey, releaseMint.publicKey, 0);
const [authorityTokenAccount, authorityTokenAccountIx] = await findOrCreateAssociatedTokenAccount(
provider.connection,
provider.wallet.publicKey,
provider.wallet.publicKey,
anchor.web3.SystemProgram.programId,
anchor.web3.SYSVAR_RENT_PUBKEY,
paymentMint
);
const [royaltyTokenAccount, royaltyTokenAccountIx] = await findOrCreateAssociatedTokenAccount(
provider.connection,
provider.wallet.publicKey,
releaseSigner,
anchor.web3.SystemProgram.programId,
anchor.web3.SYSVAR_RENT_PUBKEY,
paymentMint,
true
);
const [hubCollaborator] = await anchor.web3.PublicKey.findProgramAddress(
[
Buffer.from(anchor.utils.bytes.utf8.encode('nina-hub-collaborator')),
hubPubkey.toBuffer(),
provider.wallet.publicKey.toBuffer(),
],
program.programId
);
const [hubSigner] = await anchor.web3.PublicKey.findProgramAddress(
[Buffer.from(anchor.utils.bytes.utf8.encode('nina-hub-signer')), hubPubkey.toBuffer()],
program.programId
);
const [hubRelease] = await anchor.web3.PublicKey.findProgramAddress(
[Buffer.from(anchor.utils.bytes.utf8.encode('nina-hub-release')), hubPubkey.toBuffer(), release.toBuffer()],
program.programId
);
const [hubContent] = await anchor.web3.PublicKey.findProgramAddress(
[Buffer.from(anchor.utils.bytes.utf8.encode('nina-hub-content')), hubPubkey.toBuffer(), release.toBuffer()],
program.programId
);
let [hubWallet] = await findOrCreateAssociatedTokenAccount(
provider.connection,
provider.wallet.publicKey,
hubSigner,
anchor.web3.SystemProgram.programId,
anchor.web3.SYSVAR_RENT_PUBKEY,
paymentMint
);
let instructions = [...releaseMintIx, royaltyTokenAccountIx];
if (authorityTokenAccountIx) {
instructions.push(authorityTokenAccountIx);
}
const editionAmount = isOpen ? MAX_INT : amount;
const config = {
amountTotalSupply: new anchor.BN(editionAmount),
amountToArtistTokenAccount: new anchor.BN(0),
amountToVaultTokenAccount: new anchor.BN(0),
resalePercentage: new anchor.BN(resalePercentage * 10000),
price: new anchor.BN(uiToNative(retailPrice, paymentMint)),
releaseDatetime: new anchor.BN(Date.now() / 1000),
};
const bumps = {
release: releaseBump,
signer: releaseSignerBump,
};
const metadataProgram = new anchor.web3.PublicKey(ids.programs.metaplex);
const [metadata] = await anchor.web3.PublicKey.findProgramAddress(
[Buffer.from('metadata'), metadataProgram.toBuffer(), releaseMint.publicKey.toBuffer()],
metadataProgram
);
const nameBuf = Buffer.from(`${artist} - ${title}`.substring(0, 32));
const nameBufString = nameBuf.slice(0, 32).toString();
const symbolBuf = Buffer.from(catalogNumber.substring(0, 10));
const symbolBufString = symbolBuf.slice(0, 10).toString();
const metadataData = {
name: nameBufString,
symbol: symbolBufString,
uri: metadataUri,
sellerFeeBasisPoints: resalePercentage * 100,
};
const tx = await program.methods
.releaseInitViaHub(config, bumps, metadataData, decodeNonEncryptedByteArray(hub.handle))
.accounts({
authority: provider.wallet.publicKey,
release,
releaseSigner,
hubCollaborator,
hub: hubPubkey,
hubRelease,
hubContent,
hubSigner,
hubWallet,
releaseMint: releaseMint.publicKey,
authorityTokenAccount,
paymentMint,
royaltyTokenAccount,
tokenProgram: new anchor.web3.PublicKey(ids.programs.token),
metadata,
metadataProgram,
systemProgram: anchor.web3.SystemProgram.programId,
rent: anchor.web3.SYSVAR_RENT_PUBKEY,
})
.preInstructions(instructions)
.transaction();
tx.recentBlockhash = (await provider.connection.getRecentBlockhash()).blockhash;
tx.feePayer = provider.wallet.publicKey;
tx.partialSign(releaseMint);
const txid = await provider.wallet.sendTransaction(tx, provider.connection);
await getConfirmTransaction(txid, provider.connection);
const newRelease = await Hub.fetchHubRelease(hubPubkey.toBase58(), hubRelease.toBase58());
return newRelease;
} catch (error) {
console.warn(error);
return false;
}
};
/**
* @function initializeReleaseAndMint - Initializes a release and mints the first edition
* @param {Object} client - the Nina Client
* @param {*} hubPubkey - the hub pubkey
* @example await initializeReleaseAndMint(client, hubPubkey);
* @returns {Object} - the release, release bump, and release mint
*/
const initializeReleaseAndMint = async (client, hubPubkey) => {
try {
const program = await client.useProgram();
const releaseMint = anchor.web3.Keypair.generate();
const [release, releaseBump] = await anchor.web3.PublicKey.findProgramAddress(
[Buffer.from(anchor.utils.bytes.utf8.encode('nina-release')), releaseMint.publicKey.toBuffer()],
program.programId
);
let hubRelease;
if (hubPubkey) {
const [_hubRelease] = await anchor.web3.PublicKey.findProgramAddress(
[
Buffer.from(anchor.utils.bytes.utf8.encode('nina-hub-release')),
new anchor.web3.PublicKey(hubPubkey).toBuffer(),
release.toBuffer(),
],
program.programId
);
hubRelease = _hubRelease;
}
return {
release,
releaseBump,
releaseMint,
hubRelease,
};
} catch (error) {
console.warn(error);
return false;
}
};
/**
*
* @function releaseInit
* @param {Object} client the NinaClient
* @param {Number} retailPrice Retail price of the release.
* @param {Number} amount Amount of the release.
* @param {Number} resalePercentage Resale percentage of the release.
* @param {String} metadataUri Metadata URI of the release.
* @param {String} artist Artist of the release.
* @param {String} title Title of the release.
* @param {String} catalogNumber Catalog number of the release.
* @param {String} metadataUri Metadata URI of the release.
* @param {Boolean} isUsdc Is the release priced in USDC or not.
* @param {String} release Release of the release.
* @param {String} releaseBump Release bump of the release.
* @param {String} releaseMint Release mint of the release.
* @param {Boolean} isOpen Is the release open or not.
* @returns {Object} The created Release.
*/
export const releaseInit = async (
client,
retailPrice,
amount,
resalePercentage,
artist,
title,
catalogNumber,
metadataUri,
isUsdc = true,
release,
releaseBump,
releaseMint,
isOpen
) => {
try {
const ids = NinaClient.ids;
const { provider } = client;
const program = await client.useProgram();
const paymentMint = new anchor.web3.PublicKey(isUsdc ? ids.mints.usdc : ids.mints.wsol);
const publishingCreditMint = new anchor.web3.PublicKey(ids.mints.publishingCredit);
const [releaseSigner, releaseSignerBump] = await anchor.web3.PublicKey.findProgramAddress(
[release.toBuffer()],
program.programId
);
const releaseMintIx = await createMintInstructions(provider, provider.wallet.publicKey, releaseMint.publicKey, 0);
const [authorityTokenAccount, authorityTokenAccountIx] = await findOrCreateAssociatedTokenAccount(
provider.connection,
provider.wallet.publicKey,
provider.wallet.publicKey,
anchor.web3.SystemProgram.programId,
anchor.web3.SYSVAR_RENT_PUBKEY,
paymentMint
);
const [royaltyTokenAccount, royaltyTokenAccountIx] = await findOrCreateAssociatedTokenAccount(
provider.connection,
provider.wallet.publicKey,
releaseSigner,
anchor.web3.SystemProgram.programId,
anchor.web3.SYSVAR_RENT_PUBKEY,
paymentMint,
true
);
const [authorityPublishingCreditTokenAccount, authorityPublishingCreditTokenAccountIx] =
await findOrCreateAssociatedTokenAccount(
provider.connection,
provider.wallet.publicKey,
provider.wallet.publicKey,
anchor.web3.SystemProgram.programId,
anchor.web3.SYSVAR_RENT_PUBKEY,
publishingCreditMint
);
let instructions = [...releaseMintIx, royaltyTokenAccountIx];
if (authorityTokenAccountIx) {
instructions.push(authorityTokenAccountIx);
}
if (authorityPublishingCreditTokenAccountIx) {
instructions.push(authorityPublishingCreditTokenAccountIx);
}
let now = new Date();
const editionAmount = isOpen ? MAX_INT : amount;
const config = {
amountTotalSupply: new anchor.BN(editionAmount),
amountToArtistTokenAccount: new anchor.BN(0),
amountToVaultTokenAccount: new anchor.BN(0),
resalePercentage: new anchor.BN(resalePercentage * 10000),
price: new anchor.BN(uiToNative(retailPrice, paymentMint)),
releaseDatetime: new anchor.BN(now.getTime() / 1000),
};
const metadataProgram = new anchor.web3.PublicKey(ids.programs.metaplex);
const [metadata] = await anchor.web3.PublicKey.findProgramAddress(
[Buffer.from('metadata'), metadataProgram.toBuffer(), releaseMint.publicKey.toBuffer()],
metadataProgram
);
const nameBuf = Buffer.from(`${artist} - ${title}`.substring(0, 32));
const nameBufString = nameBuf.slice(0, 32).toString();
const symbolBuf = Buffer.from(catalogNumber.substring(0, 10));
const symbolBufString = symbolBuf.slice(0, 10).toString();
const metadataData = {
name: nameBufString,
symbol: symbolBufString,
uri: metadataUri,
sellerFeeBasisPoints: resalePercentage * 100,
};
const bumps = {
release: releaseBump,
signer: releaseSignerBump,
};
const tx = await program.methods
.releaseInit(config, bumps, metadataData)
.accounts({
release,
releaseSigner,
releaseMint: releaseMint.publicKey,
payer: provider.wallet.publicKey,
authority: provider.wallet.publicKey,
authorityTokenAccount: authorityTokenAccount,
paymentMint,
royaltyTokenAccount,
metadata,
metadataProgram,
systemProgram: anchor.web3.SystemProgram.programId,
tokenProgram: TOKEN_PROGRAM_ID,
rent: anchor.web3.SYSVAR_RENT_PUBKEY,
})
.preInstructions(instructions)
.transaction();
tx.recentBlockhash = (await provider.connection.getRecentBlockhash()).blockhash;
tx.feePayer = provider.wallet.publicKey;
tx.partialSign(releaseMint);
const txid = await provider.wallet.sendTransaction(tx, provider.connection);
await getConfirmTransaction(txid, provider.connection);
const createdRelease = await fetch(release.toBase58());
return createdRelease;
} catch (error) {
console.warn(error);
return false;
}
};
/**
* @function closeRelease
* @param {Object} client the NinaClient
* @param {String} releasePublicKey Public Key of the release.
* @example await closeRelease(ninaClient, 'releasePublicKey');
* @returns {Object} The closed Release.
*/
export const closeRelease = async (client, releasePublicKey) => {
try {
const { provider } = client;
const program = await client.useProgram();
const release = await program.account.release.fetch(new anchor.web3.PublicKey(releasePublicKey));
const tx = await program.methods
.releaseCloseEdition()
.accounts({
authority: provider.wallet.publicKey,
release: new anchor.web3.PublicKey(releasePublicKey),
releaseSigner: release.releaseSigner,
releaseMint: release.releaseMint,
})
.transaction();
tx.recentBlockhash = (await provider.connection.getRecentBlockhash()).blockhash;
tx.feePayer = provider.wallet.publicKey;
const txid = await provider.wallet.sendTransaction(tx, provider.connection);
await getConfirmTransaction(txid, provider.connection);
const closedRelease = await fetch(releasePublicKey);
return closedRelease;
} catch (error) {
console.warn(error);
return false;
}
};
/**
* @function collectRoyaltyForRelease
* @param {Object} client the NinaClient
* @param {String} recipient Public Key of the recipient.
* @param {String} releasePublicKey Public Key of the release.
* @param {Object} state the NinaClient state.
* @example collectRoyaltyForRelease(client, recipient, releasePublicKey, state)
* @returns {Object} the Release.
*/
export const collectRoyaltyForRelease = async (client, recipient, releasePublicKey, state) => {
if (!releasePublicKey || !recipient) {
return;
}
try {
const { provider } = client;
const program = await client.useProgram();
let release;
if (!state) {
release = await program.account.release.fetch(new anchor.web3.PublicKey(releasePublicKey));
} else {
release = state.tokenData[releasePublicKey];
}
release.paymentMint = new anchor.web3.PublicKey(release.paymentMint);
const [authorityTokenAccount, authorityTokenAccountIx] = await findOrCreateAssociatedTokenAccount(
provider.connection,
provider.wallet.publicKey,
provider.wallet.publicKey,
anchor.web3.SystemProgram.programId,
anchor.web3.SYSVAR_RENT_PUBKEY,
release.paymentMint
);
let instructions;
if (authorityTokenAccountIx) {
instructions = [authorityTokenAccountIx];
}
const tx = await program.methods
.releaseRevenueShareCollect()
.accounts({
authority: provider.wallet.publicKey,
authorityTokenAccount,
release: new anchor.web3.PublicKey(releasePublicKey),
releaseMint: release.releaseMint,
releaseSigner: release.releaseSigner,
royaltyTokenAccount: release.royaltyTokenAccount,
tokenProgram: anchor.utils.token.TOKEN_PROGRAM_ID,
})
.preInstructions(instructions || [])
.transaction();
tx.recentBlockhash = (await provider.connection.getRecentBlockhash()).blockhash;
tx.feePayer = provider.wallet.publicKey;
const txid = await provider.wallet.sendTransaction(tx, provider.connection);
await getConfirmTransaction(txid, provider.connection);
const collectedRelease = await fetch(releasePublicKey);
return collectedRelease;
} catch (error) {
console.warn(error);
return false;
}
};
/**
* @function addRoyaltyRecipient
* @param {Object} client - the NinaClient
* @param {String} release - the release
* @param {Object} updateData - the data to update the release with
* @param {String} releasePublicKey - the Public Key of the release
* @example addRoyaltyRecipient(client, recipient, updateData, releasePublicKey)
* @returns {String} The Public Key of the recipient
*/
export const addRoyaltyRecipient = async (client, release, updateData, releasePublicKey) => {
try {
const { provider } = client;
const program = await client.useProgram();
const releasePubkey = new anchor.web3.PublicKey(releasePublicKey);
if (!release) {
release = await program.account.release.fetch(releasePubkey);
}
const recipientPublicKey = new anchor.web3.PublicKey(updateData.recipientAddress);
const updateAmount = updateData.percentShare * 10000;
let [newRoyaltyRecipientTokenAccount, newRoyaltyRecipientTokenAccountIx] = await findOrCreateAssociatedTokenAccount(
provider.connection,
provider.wallet.publicKey,
recipientPublicKey,
anchor.web3.SystemProgram.programId,
anchor.web3.SYSVAR_RENT_PUBKEY,
new anchor.web3.PublicKey(release.paymentMint)
);
let [authorityTokenAccount, authorityTokenAccountIx] = await findOrCreateAssociatedTokenAccount(
provider.connection,
provider.wallet.publicKey,
provider.wallet.publicKey,
anchor.web3.SystemProgram.programId,
anchor.web3.SYSVAR_RENT_PUBKEY,
new anchor.web3.PublicKey(release.paymentMint)
);
if (newRoyaltyRecipientTokenAccountIx) {
request.instructions = [newRoyaltyRecipientTokenAccountIx];
}
if (authorityTokenAccountIx) {
request.instructions = [authorityTokenAccountIx];
}
const tx = await program.methods
.releaseRevenueShareTransfer(new anchor.BN(updateAmount))
.accounts({
authority: provider.wallet.publicKey,
authorityTokenAccount,
release: releasePublicKey,
releaseMint: new anchor.web3.PublicKey(release.releaseMint),
releaseSigner: new anchor.web3.PublicKey(release.releaseSigner),
royaltyTokenAccount: release.royaltyTokenAccount,
newRoyaltyRecipient: recipientPublicKey,
newRoyaltyRecipientTokenAccount,
tokenProgram: TOKEN_PROGRAM_ID,
rent: anchor.web3.SYSVAR_RENT_PUBKEY,
})
.transaction();
tx.recentBlockhash = (await provider.connection.getRecentBlockhash()).blockhash;
tx.feePayer = provider.wallet.publicKey;
const txid = await provider.wallet.sendTransaction(tx, provider.connection);
await getConfirmTransaction(txid, provider.connection);
return recipientPublicKey;
} catch (error) {
console.warn(error);
return false;
}
};
export default {
fetchAll,
fetch,
fetchCollectors,
fetchHubs,
fetchExchanges,
fetchRevenueShareRecipients,
purchaseViaHub,
releaseInitViaHub,
initializeReleaseAndMint,
releasePurchase,
releaseInit,
closeRelease,
collectRoyaltyForRelease,
addRoyaltyRecipient,
};