UNPKG

@tatumio/tatum-v1

Version:

Tatum API client allows browsers and Node.js clients to interact with Tatum API.

340 lines 31.9 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.sendMarketplaceCancelListing = exports.sendMarketplaceBuyListing = exports.sendMarketplaceCreateListing = exports.sendMarketplaceApproveErc20Spending = exports.sendMarketplaceUpdateFeeRecipient = exports.sendMarketplaceUpdateFee = exports.prepareMarketplaceCancelListing = exports.prepareMarketplaceBuyListing = exports.prepareMarketplaceCreateListing = exports.prepareMarketplaceApproveErc20Spending = exports.prepareMarketplaceUpdateFeeRecipient = exports.prepareMarketplaceUpdateFee = exports.prepareDeployMarketplaceListing = exports.deployMarketplaceListing = exports.getMarketplaceFeeRecipient = exports.getMarketplaceListing = exports.getMarketplaceFee = void 0; const bignumber_js_1 = __importDefault(require("bignumber.js")); const tatum_1 = require("../../connector/tatum"); const fungible_1 = require("../../fungible"); const helpers_1 = require("../../helpers"); const model_1 = require("../../model"); const transaction_1 = require("../../transaction"); var ListingState; (function (ListingState) { ListingState["INITIATED"] = "0"; ListingState["SOLD"] = "1"; ListingState["CANCELLED"] = "2"; })(ListingState || (ListingState = {})); /** * For more details, see <a href="https://apidoc.tatum.io/#operation/GetMarketplaceFee" target="_blank">Tatum API documentation</a> */ const getMarketplaceFee = async (chain, contractAddress) => tatum_1.get(`/v3/blockchain/marketplace/listing/${chain}/${contractAddress}/fee`); exports.getMarketplaceFee = getMarketplaceFee; /** * For more details, see <a href="https://apidoc.tatum.io/#operation/GetMarketplaceListing" target="_blank">Tatum API documentation</a> */ const getMarketplaceListing = async (chain, contractAddress, listingId) => tatum_1.get(`/v3/blockchain/marketplace/listing/${chain}/${contractAddress}/listing/${listingId}`); exports.getMarketplaceListing = getMarketplaceListing; /** * For more details, see <a href="https://apidoc.tatum.io/#operation/GetMarketplaceFeeRecipient" target="_blank">Tatum API documentation</a> */ const getMarketplaceFeeRecipient = async (chain, contractAddress) => tatum_1.get(`/v3/blockchain/marketplace/listing/${chain}/${contractAddress}/recipient`); exports.getMarketplaceFeeRecipient = getMarketplaceFeeRecipient; /** * Deploy new smart contract for NFT marketplace logic. Smart contract enables marketplace operator to create new listing for NFT (ERC-721/1155). * Operator can set a fee in percentage, which will be paid on top of the price of the asset. * Listing can be offered for native asset - ETH, BSC, etc. - or any ERC20 token - this is configurable during listing creation. * Once the listing is created, seller must send the NFT asset to the smart contract. * Buyer will buy the asset from the listing using native asset - send assets along the buyAssetFromListing() smart contract call, or via ERC20 token. * Buyer of the listing must perform approval for the smart contract to access ERC20 token, before the actual buyAssetFromListing() method is called. * Once both assets - from buyer and seller - are in the smart contract, NFT is sent to the buyer, price is sent to the seller * and marketplace fee is set to the operator. * @param testnet chain to work with * @param body request data * @param provider optional provider to enter. if not present, Tatum Web3 will be used. * @returns {txId: string} Transaction ID of the operation, or signatureID in case of Tatum KMS */ const deployMarketplaceListing = async (testnet, body, provider) => { switch (body.chain) { case model_1.Currency.CELO: return await transaction_1.sendCeloDeployMarketplaceListingSignedTransaction(testnet, body, provider); case model_1.Currency.ONE: return await transaction_1.sendOneDeployMarketplaceListingSignedTransaction(testnet, body, provider); case model_1.Currency.ETH: return await transaction_1.sendEthDeployMarketplaceListingSignedTransaction(body, provider); case model_1.Currency.BSC: return await transaction_1.sendBscDeployMarketplaceListingSignedTransaction(body, provider); case model_1.Currency.MATIC: return await transaction_1.sendPolygonDeployMarketplaceListingSignedTransaction(testnet, body, provider); case model_1.Currency.KLAY: return await transaction_1.sendKlaytnDeployMarketplaceListingSignedTransaction(testnet, body, provider); // case Currency.TRON: // return await sendTronDeployMarketplaceListingSignedTransaction(testnet, body as DeployTronMarketplaceListing, provider) default: throw new Error('Unsupported chain'); } }; exports.deployMarketplaceListing = deployMarketplaceListing; /** * Prepare signed transaction for deploy new smart contract for NFT marketplace logic. Smart contract enables marketplace operator to create new listing for NFT (ERC-721/1155). * Operator can set a fee in percentage, which will be paid on top of the price of the asset. * Listing can be offered for native asset - ETH, BSC, etc. - or any ERC20 token - this is configurable during listing creation. * Once the listing is created, seller must send the NFT asset to the smart contract. * Buyer will buy the asset from the listing using native asset - send assets along the buyAssetFromListing() smart contract call, or via ERC20 token. * Buyer of the listing must perform approval for the smart contract to access ERC20 token, before the actual buyAssetFromListing() method is called. * Once both assets - from buyer and seller - are in the smart contract, NFT is sent to the buyer, price is sent to the seller * and marketplace fee is set to the operator. * @param testnet chain to work with * @param body request data * @param provider optional provider to enter. if not present, Tatum Web3 will be used. * @returns {txId: string} Transaction ID of the operation, or signatureID in case of Tatum KMS */ const prepareDeployMarketplaceListing = async (testnet, body, provider) => { switch (body.chain) { case model_1.Currency.CELO: return await transaction_1.prepareCeloDeployMarketplaceListingSignedTransaction(testnet, body, provider); case model_1.Currency.ONE: return await transaction_1.prepareOneDeployMarketplaceListingSignedTransaction(testnet, body, provider); case model_1.Currency.ETH: return await transaction_1.prepareEthDeployMarketplaceListingSignedTransaction(body, provider); case model_1.Currency.BSC: return await transaction_1.prepareBscDeployMarketplaceListingSignedTransaction(body, provider); case model_1.Currency.MATIC: return await transaction_1.preparePolygonDeployMarketplaceListingSignedTransaction(testnet, body, provider); case model_1.Currency.KLAY: return await transaction_1.prepareKlaytnDeployMarketplaceListingSignedTransaction(testnet, body, provider); // case Currency.TRON: // return await prepareTronDeployMarketplaceListingSignedTransaction(testnet, body as DeployTronMarketplaceListing, provider) default: throw new Error('Unsupported chain'); } }; exports.prepareDeployMarketplaceListing = prepareDeployMarketplaceListing; /** * Update marketplace fee. * @param testnet chain to work with * @param body request data * @param provider optional provider to enter. if not present, Tatum Web3 will be used. * @returns {txId: string} Transaction ID of the operation, or signatureID in case of Tatum KMS */ const prepareMarketplaceUpdateFee = async (testnet, body, provider) => { await tatum_1.validateBody(body, body.chain === model_1.Currency.TRON ? model_1.UpdateTronMarketplaceFee : model_1.UpdateMarketplaceFee); const params = [`0x${new bignumber_js_1.default(body.marketplaceFee).toString(16)}`]; if (body.chain === model_1.Currency.TRON) { throw new Error('Unsupported chain'); // return await helperPrepareSCCall(testnet, body, UpdateTronMarketplaceFee, 'setMarketplaceFee', // [ // {type: 'uint256', value: params[0]}, // ], 'setMarketplaceFee(uint256)', provider) } else { return await helpers_1.helperPrepareSCCall(testnet, body, model_1.UpdateMarketplaceFee, 'setMarketplaceFee', params, undefined, provider); } }; exports.prepareMarketplaceUpdateFee = prepareMarketplaceUpdateFee; /** * Update marketplace fee recipient. * @param testnet chain to work with * @param body request data * @param provider optional provider to enter. if not present, Tatum Web3 will be used. * @returns {txId: string} Transaction ID of the operation, or signatureID in case of Tatum KMS */ const prepareMarketplaceUpdateFeeRecipient = async (testnet, body, provider) => { await tatum_1.validateBody(body, body.chain === model_1.Currency.TRON ? model_1.UpdateTronMarketplaceFeeRecipient : model_1.UpdateMarketplaceFeeRecipient); const params = [body.feeRecipient]; if (body.chain === model_1.Currency.TRON) { throw new Error('Unsupported chain'); // return await helperPrepareSCCall(testnet, body, UpdateTronMarketplaceFeeRecipient, 'setMarketplaceFeeRecipient', // [ // {type: 'address', value: convertAddressToHex(params[0])}, // ], 'setMarketplaceFeeRecipient(address)', provider) } else { return await helpers_1.helperPrepareSCCall(testnet, body, model_1.UpdateMarketplaceFeeRecipient, 'setMarketplaceFeeRecipient', params, undefined, provider); } }; exports.prepareMarketplaceUpdateFeeRecipient = prepareMarketplaceUpdateFeeRecipient; /** * Approve ERC20 spending for marketplace to perform buy with ERC20 token. * @param testnet chain to work with * @param body request data * @param provider optional provider to enter. if not present, Tatum Web3 will be used. * @returns {txId: string} Transaction ID of the operation, or signatureID in case of Tatum KMS */ const prepareMarketplaceApproveErc20Spending = async (testnet, body, provider) => { return fungible_1.prepareApproveErc20(testnet, body, provider); }; exports.prepareMarketplaceApproveErc20Spending = prepareMarketplaceApproveErc20Spending; /** * Create new listing on the marketplace. * After listing is created, seller must send the asset to the marketplace smart contract. * Only listing for existing NFTs can be created - seller must be owner of the NFT asset. * @param testnet chain to work with * @param body request data * @param provider optional provider to enter. if not present, Tatum Web3 will be used. * @returns {txId: string} Transaction ID of the operation, or signatureID in case of Tatum KMS */ const prepareMarketplaceCreateListing = async (testnet, body, provider) => { await tatum_1.validateBody(body, body.chain === model_1.Currency.TRON ? model_1.CreateTronMarketplaceListing : model_1.CreateMarketplaceListing); const decimals = body.erc20Address ? await fungible_1.getErc20Decimals(testnet, body.chain, body.erc20Address, provider) : 18; const params = [body.listingId, body.isErc721, body.nftAddress.trim(), `0x${new bignumber_js_1.default(body.tokenId).toString(16)}`, `0x${new bignumber_js_1.default(body.price).multipliedBy(10 ** decimals).toString(16)}`, body.seller.trim(), `0x${new bignumber_js_1.default(body.amount || 0).toString(16)}`, body.erc20Address || '0x0000000000000000000000000000000000000000']; if (body.chain === model_1.Currency.TRON) { throw new Error('Unsupported chain'); // if (!body.erc20Address) { // params[7] = 'T9yD14Nj9j7xAB4dbGeiX9h8unkKHxuWwb'; // } // return await helperPrepareSCCall(testnet, body, CreateTronMarketplaceListing, 'createListing', // [ // {type: 'string', value: params[0]}, // {type: 'bool', value: params[1]}, // {type: 'address', value: convertAddressToHex(params[2] as string)}, // {type: 'uint256', value: params[3]}, // {type: 'uint256', value: params[4]}, // {type: 'address', value: convertAddressToHex(params[5] as string)}, // {type: 'uint256', value: params[6]}, // {type: 'address', value: convertAddressToHex(params[7] as string)}, // ], 'createListing(string,bool,address,uint256,uint256,address,uint256,address)', provider) } else { if (!body.isErc721) { body.amount = undefined; } return await helpers_1.helperPrepareSCCall(testnet, body, model_1.CreateMarketplaceListing, 'createListing', params, undefined, provider); } }; exports.prepareMarketplaceCreateListing = prepareMarketplaceCreateListing; /** * Buy listing on the marketplace. Buyer must either send native assets with this operation, or approve ERC20 token spending before. * After listing is sold, it's in a pending state to be processed by the marketplace. Noone receives the assets unless the marketplace operator processes that. * @param testnet chain to work with * @param body request data * @param provider optional provider to enter. if not present, Tatum Web3 will be used. * @returns {txId: string} Transaction ID of the operation, or signatureID in case of Tatum KMS */ const prepareMarketplaceBuyListing = async (testnet, body, provider) => { await tatum_1.validateBody(body, body.chain === model_1.Currency.TRON ? model_1.InvokeTronMarketplaceListingOperation : model_1.InvokeMarketplaceListingOperation); const params = [body.listingId, body.erc20Address || '0x0000000000000000000000000000000000000000']; let methodName = 'buyAssetFromListing'; if (body.erc20Address) { body.amount = undefined; if (body.buyer) { params.push(body.buyer.trim()); methodName = 'buyAssetFromListingForExternalBuyer'; } } if (body.chain === model_1.Currency.TRON) { throw new Error('Unsupported chain'); // return await helperPrepareSCCall(testnet, body, InvokeTronMarketplaceListingOperation, 'buyAssetFromListing', // [ // {type: 'string', value: params[0]}, // {type: 'address', value: convertAddressToHex(params[1])}, // ], 'buyAssetFromListing(string,address)', provider); } else { return await helpers_1.helperPrepareSCCall(testnet, body, model_1.InvokeMarketplaceListingOperation, methodName, params, undefined, provider); } }; exports.prepareMarketplaceBuyListing = prepareMarketplaceBuyListing; /** * Cancel listing on the marketplace. Only possible for the seller or the operator. There must be no buyer present for that listing. NFT asset is sent back to the seller. * @param testnet chain to work with * @param body request data * @param provider optional provider to enter. if not present, Tatum Web3 will be used. * @returns {txId: string} Transaction ID of the operation, or signatureID in case of Tatum KMS */ const prepareMarketplaceCancelListing = async (testnet, body, provider) => { await tatum_1.validateBody(body, body.chain === model_1.Currency.TRON ? model_1.InvokeTronMarketplaceListingOperation : model_1.InvokeMarketplaceListingOperation); const params = [body.listingId]; if (body.chain === model_1.Currency.TRON) { throw new Error('Unsupported chain'); // return await helperPrepareSCCall(testnet, body, InvokeTronMarketplaceListingOperation, 'cancelListing', // [ // {type: 'string', value: params[0]}, // ], 'cancelListing(string)', provider) } else { return await helpers_1.helperPrepareSCCall(testnet, body, model_1.InvokeMarketplaceListingOperation, 'cancelListing', params, undefined, provider); } }; exports.prepareMarketplaceCancelListing = prepareMarketplaceCancelListing; /** * Update marketplace fee. * @param testnet chain to work with * @param body request data * @param provider optional provider to enter. if not present, Tatum Web3 will be used. * @returns {txId: string} Transaction ID of the operation, or signatureID in case of Tatum KMS */ const sendMarketplaceUpdateFee = async (testnet, body, provider) => { if (body.signatureId) { return await tatum_1.put(`v3/blockchain/marketplace/listing/recipient`, body); } return helpers_1.helperBroadcastTx(body.chain, await exports.prepareMarketplaceUpdateFee(testnet, body, provider)); }; exports.sendMarketplaceUpdateFee = sendMarketplaceUpdateFee; /** * Update marketplace fee recipient. * @param testnet chain to work with * @param body request data * @param provider optional provider to enter. if not present, Tatum Web3 will be used. * @returns {txId: string} Transaction ID of the operation, or signatureID in case of Tatum KMS */ const sendMarketplaceUpdateFeeRecipient = async (testnet, body, provider) => { if (body.signatureId) { return await tatum_1.put(`v3/blockchain/marketplace/listing/fee`, body); } return helpers_1.helperBroadcastTx(body.chain, await exports.prepareMarketplaceUpdateFeeRecipient(testnet, body, provider)); }; exports.sendMarketplaceUpdateFeeRecipient = sendMarketplaceUpdateFeeRecipient; /** * Approve ERC20 spending for marketplace to perform buy with ERC20 token. * @param testnet chain to work with * @param body request data * @param provider optional provider to enter. if not present, Tatum Web3 will be used. * @returns {txId: string} Transaction ID of the operation, or signatureID in case of Tatum KMS */ const sendMarketplaceApproveErc20Spending = async (testnet, body, provider) => { if (body.signatureId) { return await tatum_1.post(`v3/blockchain/token/approve`, body); } return helpers_1.helperBroadcastTx(body.chain, await exports.prepareMarketplaceApproveErc20Spending(testnet, body, provider)); }; exports.sendMarketplaceApproveErc20Spending = sendMarketplaceApproveErc20Spending; /** * Create new listing on the marketplace. * After listing is created, seller must send the asset to the marketplace smart contract. * Only listing for existing NFTs can be created - seller must be owner of the NFT asset. * @param testnet chain to work with * @param body request data * @param provider optional provider to enter. if not present, Tatum Web3 will be used. * @returns {txId: string} Transaction ID of the operation, or signatureID in case of Tatum KMS */ const sendMarketplaceCreateListing = async (testnet, body, provider) => { if (body.signatureId) { return await tatum_1.post(`v3/blockchain/marketplace/listing/sell`, body); } return helpers_1.helperBroadcastTx(body.chain, await exports.prepareMarketplaceCreateListing(testnet, body, provider)); }; exports.sendMarketplaceCreateListing = sendMarketplaceCreateListing; /** * Buy listing on the marketplace. Buyer must either send native assets with this operation, or approve ERC20 token spending before. * After listing is sold, it's in a pending state to be processed by the marketplace. Noone receives the assets unless the marketplace operator processes that. * @param testnet chain to work with * @param body request data * @param provider optional provider to enter. if not present, Tatum Web3 will be used. * @returns {txId: string} Transaction ID of the operation, or signatureID in case of Tatum KMS */ const sendMarketplaceBuyListing = async (testnet, body, provider) => { if (body.signatureId) { return await tatum_1.post(`v3/blockchain/marketplace/listing/buy`, body); } return helpers_1.helperBroadcastTx(body.chain, await exports.prepareMarketplaceBuyListing(testnet, body, provider)); }; exports.sendMarketplaceBuyListing = sendMarketplaceBuyListing; /** * Cancel listing on the marketplace. Only possible for the seller or the operator. There must be no buyer present for that listing. NFT asset is sent back to the seller. * @param testnet chain to work with * @param body request data * @param provider optional provider to enter. if not present, Tatum Web3 will be used. * @returns {txId: string} Transaction ID of the operation, or signatureID in case of Tatum KMS */ const sendMarketplaceCancelListing = async (testnet, body, provider) => { if (body.signatureId) { return await tatum_1.post(`v3/blockchain/marketplace/listing/cancel`, body); } return helpers_1.helperBroadcastTx(body.chain, await exports.prepareMarketplaceCancelListing(testnet, body, provider)); }; exports.sendMarketplaceCancelListing = sendMarketplaceCancelListing; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGlzdGluZy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9uZnQvbWFya2V0cGxhY2UvbGlzdGluZy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQSxnRUFBcUM7QUFDckMsaURBQXFFO0FBQ3JFLDZDQUF1RTtBQUN2RSwyQ0FBdUU7QUFDdkUsdUNBYXFCO0FBQ3JCLG1EQWEyQjtBQUUzQixJQUFLLFlBSUo7QUFKRCxXQUFLLFlBQVk7SUFDZiwrQkFBZSxDQUFBO0lBQ2YsMEJBQVUsQ0FBQTtJQUNWLCtCQUFlLENBQUE7QUFDakIsQ0FBQyxFQUpJLFlBQVksS0FBWixZQUFZLFFBSWhCO0FBc0REOztHQUVHO0FBQ0ksTUFBTSxpQkFBaUIsR0FBRyxLQUFLLEVBQUUsS0FBZSxFQUFFLGVBQXVCLEVBQW1CLEVBQUUsQ0FDbkcsV0FBRyxDQUFDLHNDQUFzQyxLQUFLLElBQUksZUFBZSxNQUFNLENBQUMsQ0FBQztBQUQvRCxRQUFBLGlCQUFpQixxQkFDOEM7QUFFNUU7O0dBRUc7QUFDSSxNQUFNLHFCQUFxQixHQUFHLEtBQUssRUFBRSxLQUFlLEVBQUUsZUFBdUIsRUFBRSxTQUFpQixFQUErQixFQUFFLENBQ3RJLFdBQUcsQ0FBQyxzQ0FBc0MsS0FBSyxJQUFJLGVBQWUsWUFBWSxTQUFTLEVBQUUsQ0FBQyxDQUFDO0FBRGhGLFFBQUEscUJBQXFCLHlCQUMyRDtBQUU3Rjs7R0FFRztBQUNJLE1BQU0sMEJBQTBCLEdBQUcsS0FBSyxFQUFFLEtBQWUsRUFBRSxlQUF1QixFQUFnQyxFQUFFLENBQ3pILFdBQUcsQ0FBQyxzQ0FBc0MsS0FBSyxJQUFJLGVBQWUsWUFBWSxDQUFDLENBQUM7QUFEckUsUUFBQSwwQkFBMEIsOEJBQzJDO0FBRWxGOzs7Ozs7Ozs7Ozs7O0dBYUc7QUFDSSxNQUFNLHdCQUF3QixHQUFHLEtBQUssRUFBRSxPQUFnQixFQUFFLElBQTZELEVBQUUsUUFBaUIsRUFBRSxFQUFFO0lBQ25KLFFBQVEs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