@tatumio/tatum-v1
Version:
Tatum API client allows browsers and Node.js clients to interact with Tatum API.
340 lines • 31.9 kB
JavaScript
;
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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