@tatumio/tatum-v1
Version:
Tatum API client allows browsers and Node.js clients to interact with Tatum API.
420 lines • 35.1 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.sendAddNFTMinter = exports.prepareAddNFTMinter = exports.transferNFT = exports.updateCashbackForAuthorNFT = exports.burnNFT = exports.mintMultipleNFTWithUri = exports.mintNFTWithUri = exports.createNFT = exports.deployNFT = exports.getNFTRoyalty = exports.getNFTImage = exports.getNFTMetadataURI = exports.getNFTContractAddress = exports.getNFTProvenanceData = exports.getNFTsByAddress = exports.mintNFT = void 0;
const tatum_1 = require("../connector/tatum");
const erc721_abi_1 = __importDefault(require("../contracts/erc721Cashback/erc721_abi"));
const helpers_1 = require("../helpers");
const model_1 = require("../model");
const storage_1 = require("../storage");
const transaction_1 = require("../transaction");
const mintNFT = (body) => tatum_1.post(`/v3/nft/mint`, body);
exports.mintNFT = mintNFT;
/**
* For more details, see <a href="https://apidoc.tatum.io/#operation/NftGetBalanceErc721" target="_blank">Tatum API documentation</a>
*/
const getNFTsByAddress = async (chain, contractAddress, address) => tatum_1.get(`/v3/nft/balance/${chain}/${contractAddress}/${address}`);
exports.getNFTsByAddress = getNFTsByAddress;
/**
* For more details, see <a href="https://apidoc.tatum.io/#operation/NftProvenanceReadData" target="_blank">Tatum API documentation</a>
*/
const getNFTProvenanceData = async (chain, contractAddress, tokenId) => tatum_1.get(`/v3/nft/provenance/${chain}/${contractAddress}/${tokenId}`);
exports.getNFTProvenanceData = getNFTProvenanceData;
/**
* For more details, see <a href="https://apidoc.tatum.io/#operation/NftGetContractAddress" target="_blank">Tatum API documentation</a>
*/
const getNFTContractAddress = async (chain, txId) => tatum_1.get(`/v3/nft/address/${chain}/${txId}`);
exports.getNFTContractAddress = getNFTContractAddress;
/**
* For more details, see <a href="https://apidoc.tatum.io/#operation/NftGetMetadataErc721" target="_blank">Tatum API documentation</a>
*/
const getNFTMetadataURI = async (chain, contractAddress, tokenId, account) => {
let url = `/v3/nft/metadata/${chain}/${contractAddress}/${tokenId}`;
if (account) {
url += `?account=${account}`;
}
return tatum_1.get(url);
};
exports.getNFTMetadataURI = getNFTMetadataURI;
/**
* Get IPFS image URL from the NFT with the IPFS Metadata scheme. URL
* @param chain chain where NFT token is
* @param contractAddress contract address of the NFT token
* @param tokenId ID of the token
* @param account FLOW only - account where the token is minted
*/
const getNFTImage = async (chain, contractAddress, tokenId, account) => {
const { data: metadata } = await exports.getNFTMetadataURI(chain, contractAddress, tokenId, account);
const metadataUrl = `https://gateway.pinata.cloud/ipfs/${metadata.replace('ipfs://', '')}`;
const { data } = await tatum_1.axios.get(metadataUrl);
const imageUrl = data.image;
return {
originalUrl: imageUrl,
publicUrl: `https://gateway.pinata.cloud/ipfs/${imageUrl.replace('ipfs://', '')}`,
};
};
exports.getNFTImage = getNFTImage;
/**
* For more details, see <a href="https://apidoc.tatum.io/#operation/NftGetRoyaltyErc721" target="_blank">Tatum API documentation</a>
*/
const getNFTRoyalty = async (chain, contractAddress, tokenId) => tatum_1.get(`/v3/nft/royalty/${chain}/${contractAddress}/${tokenId}`);
exports.getNFTRoyalty = getNFTRoyalty;
/**
* Deploy new NFT smart contract, which will be used for later minting.
* @param testnet if we use testnet or not
* @param body body of the mint request
* @param provider optional provider do broadcast tx
*/
const deployNFT = async (testnet, body, provider) => {
switch (body.chain) {
case model_1.Currency.CELO:
return transaction_1.sendCeloDeployErc721Transaction(testnet, body, provider);
case model_1.Currency.ETH:
return transaction_1.sendDeployErc721Transaction(body, provider);
case model_1.Currency.MATIC:
return transaction_1.sendPolygonDeployErc721SignedTransaction(testnet, body, provider);
case model_1.Currency.KLAY:
return transaction_1.sendKlaytnDeployErc721SignedTransaction(testnet, body, provider);
case model_1.Currency.ONE:
return transaction_1.sendOneDeploy721SignedTransaction(testnet, body, provider);
case model_1.Currency.TRON:
return transaction_1.sendTronDeployTrc721SignedTransaction(testnet, body);
case model_1.Currency.BSC:
return transaction_1.sendDeployBep721Transaction(body, provider);
case model_1.Currency.FLOW:
return tatum_1.post('/v3/nft/deploy', body, model_1.FlowDeployNft);
default:
throw new Error('Unsupported currency');
}
};
exports.deployNFT = deployNFT;
/**
* Mint new NFT token with metadata stored on the IPFS.
* @param testnet if we use testnet or not
* @param body body of the mint request
* @param file file to be stored on the IPFS
* @param name name of the file
* @param description description of the file
* @param scheme optional JSON Metadata scheme
* @param provider optional provider do broadcast tx
*/
const createNFT = async (testnet, body, file, name, description, scheme, provider) => {
const metadata = scheme || {};
metadata.name = name;
if (description) {
metadata.description = description;
}
const { ipfsHash } = await storage_1.ipfsUpload(file, name);
metadata.image = `ipfs://${ipfsHash}`;
const { ipfsHash: metadataHash } = await storage_1.ipfsUpload(Buffer.from(JSON.stringify(metadata)), 'metadata.json');
body.url = `ipfs://${metadataHash}`;
if (body.chain === model_1.Currency.FLOW) {
body.privateKey = body.privateKey || body.fromPrivateKey;
}
const result = await exports.mintNFTWithUri(testnet, body, provider);
return Object.assign(Object.assign({ tokenId: body.tokenId }, result), { metadataUrl: body.url, metadataPublicUrl: `https://gateway.pinata.cloud/ipfs/${metadataHash}`, imageUrl: `ipfs://${ipfsHash}`, imagePublicUrl: `https://gateway.pinata.cloud/ipfs/${ipfsHash}` });
};
exports.createNFT = createNFT;
/**
* Mint new NFT token.
* @param testnet if we use testnet or not
* @param body body of the mint request
* @param provider optional provider do broadcast tx
*/
const mintNFTWithUri = async (testnet, body, provider) => {
switch (body.chain) {
case model_1.Currency.CELO:
if (body.provenance) {
return transaction_1.sendCeloMintErc721ProvenanceTransaction(testnet, body, provider);
}
else {
if (body.authorAddresses) {
return transaction_1.sendCeloMintCashbackErc721Transaction(testnet, body, provider);
}
else {
return transaction_1.sendCeloMintErc721Transaction(testnet, body, provider);
}
}
case model_1.Currency.ETH:
if (body.provenance) {
return transaction_1.sendMintErc721ProvenanceTransaction(body, provider);
}
else {
if (body.authorAddresses) {
return transaction_1.sendMintCashbackErc721Transaction(body, provider);
}
else {
return transaction_1.sendMintErc721Transaction(body, provider);
}
}
case model_1.Currency.MATIC:
if (body.provenance) {
return transaction_1.sendPolygonMintErc721ProvenanceSignedTransaction(testnet, body, provider);
}
else {
if (body.authorAddresses) {
return transaction_1.sendPolygonMintCashbackErc721SignedTransaction(testnet, body, provider);
}
else {
return transaction_1.sendPolygonMintErc721SignedTransaction(testnet, body, provider);
}
}
case model_1.Currency.KLAY:
if (body.provenance) {
return transaction_1.sendKlaytnMintErc721ProvenanceSignedTransaction(testnet, body, provider);
}
else {
if (body.authorAddresses) {
return transaction_1.sendKlaytnMintCashbackErc721SignedTransaction(testnet, body, provider);
}
else {
return transaction_1.sendKlaytnMintErc721SignedTransaction(testnet, body, provider);
}
}
case model_1.Currency.ONE:
if (body.provenance) {
return transaction_1.sendOneMint721ProvenanceSignedTransaction(testnet, body, provider);
}
else {
if (body.authorAddresses) {
return transaction_1.sendOneMintCashback721SignedTransaction(testnet, body, provider);
}
else {
return transaction_1.sendOneMint721SignedTransaction(testnet, body, provider);
}
}
case model_1.Currency.TRON:
if (body.authorAddresses) {
return transaction_1.sendTronMintCashbackTrc721SignedTransaction(testnet, body);
}
else {
return transaction_1.sendTronMintTrc721SignedTransaction(testnet, body);
}
case model_1.Currency.BSC:
if (body.provenance) {
return transaction_1.sendMintBep721ProvenanceTransaction(body, provider);
}
else {
if (body.authorAddresses) {
return transaction_1.sendMintBepCashback721Transaction(body, provider);
}
return transaction_1.sendMintBep721Transaction(body, provider);
}
case model_1.Currency.FLOW:
return transaction_1.sendFlowNftMintToken(testnet, body);
default:
throw new Error('Unsupported blockchain.');
}
};
exports.mintNFTWithUri = mintNFTWithUri;
/**
* Mint multiple new NFT tokens.
* @param testnet if we use testnet or not
* @param body body of the mint request
* @param provider optional provider do broadcast tx
*/
const mintMultipleNFTWithUri = async (testnet, body, provider) => {
switch (body.chain) {
case model_1.Currency.CELO:
if (body.provenance) {
return transaction_1.sendCeloMintMultipleErc721ProvenanceTransaction(testnet, body, provider);
}
else {
if (body.authorAddresses) {
return transaction_1.sendCeloMintMultipleCashbackErc721Transaction(testnet, body, provider);
}
else {
return transaction_1.sendCeloMintMultipleErc721Transaction(testnet, body, provider);
}
}
case model_1.Currency.TRON:
if (body.authorAddresses) {
throw new Error('Unsupported operation.');
}
else {
return transaction_1.sendTronMintMultipleTrc721SignedTransaction(testnet, body);
}
case model_1.Currency.ETH:
if (body.provenance) {
return transaction_1.sendMintMultipleErc721ProvenanceTransaction(body, provider);
}
else {
if (body.authorAddresses) {
return transaction_1.sendEthMintMultipleCashbackErc721SignedTransaction(body, provider);
}
else {
return transaction_1.sendMintMultipleErc721Transaction(body, provider);
}
}
case model_1.Currency.MATIC:
if (body.authorAddresses) {
return transaction_1.sendPolygonMintMultipleErc721ProvenanceSignedTransaction(testnet, body, provider);
}
else {
if (body.authorAddresses) {
return transaction_1.sendPolygonMintMultipleCashbackErc721SignedTransaction(testnet, body, provider);
}
else {
return transaction_1.sendPolygonMintMultipleErc721SignedTransaction(testnet, body, provider);
}
}
case model_1.Currency.KLAY:
if (body.authorAddresses) {
return transaction_1.sendKlaytnMintMultipleErc721ProvenanceSignedTransaction(testnet, body, provider);
}
else {
if (body.authorAddresses) {
return transaction_1.sendKlaytnMintMultipleCashbackErc721SignedTransaction(testnet, body, provider);
}
else {
return transaction_1.sendKlaytnMintMultipleErc721SignedTransaction(testnet, body, provider);
}
}
case model_1.Currency.ONE:
if (body.provenance) {
return transaction_1.sendOneMintMultiple721ProvenanceSignedTransaction(testnet, body, provider);
}
else {
if (body.authorAddresses) {
return transaction_1.sendOneMintMultipleCashback721SignedTransaction(testnet, body, provider);
}
else {
return transaction_1.sendOneMintMultiple721SignedTransaction(testnet, body, provider);
}
}
case model_1.Currency.BSC:
if (body.authorAddresses) {
return transaction_1.sendMintMultipleBep721ProvenanceTransaction(body, provider);
}
else {
if (body.authorAddresses) {
return transaction_1.sendMintMultipleCashbackBep721Transaction(body, provider);
}
else {
return transaction_1.sendMintMultipleBep721Transaction(body, provider);
}
}
case model_1.Currency.FLOW:
return transaction_1.sendFlowNftMintMultipleToken(testnet, body);
default:
throw new Error('Unsupported blockchain.');
}
};
exports.mintMultipleNFTWithUri = mintMultipleNFTWithUri;
/**
* Burn new NFT token. Token will no longer exists.
* @param testnet if we use testnet or not
* @param body body of the mint request
* @param provider optional provider do broadcast tx
*/
const burnNFT = async (testnet, body, provider) => {
switch (body.chain) {
case model_1.Currency.CELO:
return transaction_1.sendCeloBurnErc721Transaction(testnet, body, provider);
case model_1.Currency.TRON:
return transaction_1.sendTronBurnTrc721SignedTransaction(testnet, body);
case model_1.Currency.ETH:
return transaction_1.sendBurnErc721Transaction(body, provider);
case model_1.Currency.MATIC:
return transaction_1.sendPolygonBurnErc721SignedTransaction(testnet, body, provider);
case model_1.Currency.KLAY:
return transaction_1.sendKlaytnBurnErc721SignedTransaction(testnet, body, provider);
case model_1.Currency.ONE:
return transaction_1.sendOneBurn721SignedTransaction(testnet, body, provider);
case model_1.Currency.BSC:
return transaction_1.sendBurnBep721Transaction(body, provider);
case model_1.Currency.FLOW:
return transaction_1.sendFlowNftBurnToken(testnet, body);
case model_1.Currency.ALGO:
return transaction_1.sendAlgoBurnNFTSignedTransaction(testnet, body, provider);
default:
throw new Error('Unsupported blockchain.');
}
};
exports.burnNFT = burnNFT;
/**
* Update royalty cashback as author of the NFT token.
* @param testnet if we use testnet or not
* @param body body of the mint request
* @param provider optional provider do broadcast tx
*/
const updateCashbackForAuthorNFT = async (testnet, body, provider) => {
switch (body.chain) {
case model_1.Currency.CELO:
return transaction_1.sendCeloUpdateCashbackForAuthorErc721Transaction(testnet, body, provider);
case model_1.Currency.ETH:
return transaction_1.sendUpdateCashbackForAuthorErc721Transaction(body, provider);
case model_1.Currency.MATIC:
return transaction_1.sendPolygonUpdateCashbackForAuthorErc721SignedTransaction(testnet, body, provider);
case model_1.Currency.KLAY:
return transaction_1.sendKlaytnUpdateCashbackForAuthorErc721SignedTransaction(testnet, body, provider);
case model_1.Currency.ONE:
return transaction_1.sendOneUpdateCashbackForAuthor721SignedTransaction(testnet, body, provider);
case model_1.Currency.TRON:
return transaction_1.sendTronUpdateCashbackForAuthorTrc721SignedTransaction(testnet, body);
case model_1.Currency.BSC:
return transaction_1.sendUpdateCashbackForAuthorBep721Transaction(body, provider);
default:
throw new Error('Unsupported blockchain.');
}
};
exports.updateCashbackForAuthorNFT = updateCashbackForAuthorNFT;
/**
* Transfer new NFT token to new recipient.
* @param testnet if we use testnet or not
* @param body body of the mint request
* @param provider optional provider do broadcast tx
*/
const transferNFT = async (testnet, body, provider) => {
switch (body.chain) {
case model_1.Currency.CELO:
return transaction_1.sendCeloTransferErc721Transaction(testnet, body, provider);
case model_1.Currency.ETH:
return transaction_1.sendErc721Transaction(body, provider);
case model_1.Currency.MATIC:
return transaction_1.sendPolygonTransferErc721SignedTransaction(testnet, body, provider);
case model_1.Currency.KLAY:
return transaction_1.sendKlaytnTransferErc721SignedTransaction(testnet, body, provider);
case model_1.Currency.ONE:
return transaction_1.sendOneTransfer721SignedTransaction(testnet, body, provider);
case model_1.Currency.TRON:
return transaction_1.sendTronTransferTrc721SignedTransaction(testnet, body);
case model_1.Currency.BSC:
return transaction_1.sendBep721Transaction(body, provider);
case model_1.Currency.FLOW:
return transaction_1.sendFlowNftTransferToken(testnet, body);
case model_1.Currency.ALGO:
return transaction_1.sendAlgoTransferNFTSignedTransaction(testnet, body, provider);
default:
throw new Error('Unsupported blockchain.');
}
};
exports.transferNFT = transferNFT;
/**
* Prepare add new minter to the NFT contract transaction.
* @param testnet if we use testnet or not
* @param body body of the add minter request
* @param provider optional provider do broadcast tx
*/
const prepareAddNFTMinter = async (testnet, body, provider) => {
await tatum_1.validateBody(body, model_1.AddMinter);
const params = ['0x9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6', body.minter];
return await helpers_1.helperPrepareSCCall(testnet, body, model_1.AddMinter, 'grantRole', params, undefined, provider, erc721_abi_1.default);
};
exports.prepareAddNFTMinter = prepareAddNFTMinter;
/**
* Add new minter to the NFT contract.
* @param testnet if we use testnet or not
* @param body body of the add minter request
* @param provider optional provider do broadcast tx
*/
const sendAddNFTMinter = async (testnet, body, provider) => {
if (body.signatureId) {
return await tatum_1.post(`v3/nft/mint/add`, body);
}
return helpers_1.helperBroadcastTx(body.chain, await exports.prepareAddNFTMinter(testnet, body, provider));
};
exports.sendAddNFTMinter = sendAddNFTMinter;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmZ0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL25mdC9uZnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQUEsOENBQW9FO0FBQ3BFLHdGQUF5RDtBQUN6RCx3Q0FBb0U7QUFDcEUsb0NBK0JrQjtBQUNsQix3Q0FBd0M7QUFDeEMsZ0RBMEV3QjtBQUVqQixNQUFNLE9BQU8sR0FBRyxDQUFDLElBQWlELEVBQTRCLEVBQUUsQ0FBQyxZQUFJLENBQUMsY0FBYyxFQUFFLElBQUksQ0FBQyxDQUFDO0FBQXRILFFBQUEsT0FBTyxXQUErRztBQUVuSTs7R0FFRztBQUNJLE1BQU0sZ0JBQWdCLEdBQUcsS0FBSyxFQUFFLEtBQWUsRUFBRSxlQUF1QixFQUFFLE9BQWUsRUFBcUIsRUFBRSxDQUNySCxXQUFHLENBQUMsbUJBQW1CLEtBQUssSUFBSSxlQUFlLElBQUksT0FBTyxFQUFFLENBQUMsQ0FBQztBQURuRCxRQUFBLGdCQUFnQixvQkFDbUM7QUFDaEU7O0dBRUc7QUFDSSxNQUFNLG9CQUFvQixHQUFHLEtBQUssRUFBRSxLQUFlLEVBQUUsZUFBdUIsRUFBRSxPQUFlLEVBQWdCLEVBQUUsQ0FDcEgsV0FBRyxDQUFDLHNCQUFzQixLQUFLLElBQUksZUFBZSxJQUFJLE9BQU8sRUFBRSxDQUFDLENBQUM7QUFEdEQsUUFBQSxvQkFBb0Isd0JBQ2tDO0FBRW5FOztHQUVHO0FBQ0ksTUFBTSxxQkFBcUIsR0FBRyxLQUFLLEVBQUUsS0FBZSxFQUFFLElBQVksRUFBd0MsRUFBRSxDQUNqSCxXQUFHLENBQUMsbUJBQW1CLEtBQUssSUFBSSxJQUFJLEVBQUUsQ0FBQyxDQUFDO0FBRDdCLFFBQUEscUJBQXFCLHlCQUNRO0FBRTFDOztHQUVHO0FBQ0ksTUFBTSxpQkFBaUIsR0FBRyxLQUFLLEVBQUUsS0FBZSxFQUFFLGVBQXVCLEVBQUUsT0FBZSxFQUFFLE9BQWdCLEVBQTZCLEVBQUU7SUFDaEosSUFBSSxHQUFHLEdBQUcsb0JBQW9C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