diff --git a/README.md b/README.md index 17311a2..7f40e7d 100644 --- a/README.md +++ b/README.md @@ -87,6 +87,133 @@ dataNft.viewDataViaMVXNativeAuth({ }); // optional params "stream" (stream out data instead of downloading file), "fwdAllHeaders"/"fwdHeaderKeys" can be used to pass on the headers like Authorization to origin Data Stream servers ``` +### 2. Interacting with Data NFT Minter + +```typescript +import { DataNftMinter } from '@itheum/sdk-mx-data-nft'; + +const dataNftMinter = new DataNftMinter('devnet' | 'testnet' | 'mainnet'); + +// View minter smart contract requirements +const requirements = await dataNftMinter.viewMinterRequirements( + new Address('erd1...') +); + +// View contract pause state +const result = await dataNftMinter.viewContractPauseState(); +``` + +#### Create a mint transaction + +Method 1: Mint a new Data NFT with Ithuem generated image and traits. +Currently only supports [nft.storage](https://nft.storage/docs/quickstart/#get-an-api-token). + +```typescript +const transaction = await nftMinter.mint( + new Address('erd1...'), + 'TEST-TOKEN', + 'https://marshal.com', + 'https://streamdata.com', + 'https://previewdata', + 1000, + 'Test Title', + 'Test Description', + { + nftStorageToken: 'API TOKEN' + } +); +``` + +Method 2: Mint a new Data NFT with custom image and traits. +Traits should be compliant with the Itheum [traits structure](#traits-structure). + +```typescript +const transaction = await nftMinter.mint( + new Address('erd1'), + 'TEST-TOKEN', + 'https://marshal.com', + 'https://streamdata.com', + 'https://previewdata', + 1000, + 'Test Title', + 'Test Description', + { + imageUrl: 'https://imageurl.com', + traitsUrl: 'https://traitsurl.com' + } +); +``` + +#### Create a burn transaction + +```typescript +const transaction = await dataNftMarket.burn( + new Address('erd1'), + dataNftNonce, + quantityToBurn +); +``` + +### 3. Interacting with Data NFT Marketplace + +```typescript +import { DataNftMarket } from '@itheum/sdk-mx-data-nft'; + +const dataNftMarket = new DataNftMarket('devnet' | 'testnet' | 'mainnet'); + +// View requirements +const result = await dataNftMarket.viewRequirements(); + +// View address listed offers +const result = await dataNftMarket.viewAddressListedOffers(new Address('')); + +// View address paged offers +const result = await dataNftMarket.viewAddressPagedOffers( + 1, + 10, + new Address('') +); + +// View address total offers +const result = await dataNftMarket.viewAddressTotalOffers(new Address('')); + +// View address cancelled offers +const result = await dataNftMarket.viewAddressCancelledOffers(new Address('')); + +// View offers paged +const result = await dataNftMarket.viewPagedOffers(1, 10); + +// View offers +const result = await dataNftMarket.viewOffers(); + +// View number of offers listed +const result = await dataNftMarket.viewNumberOfOffers(); + +// View contract pause state +const result = await dataNftMarket.viewContractPauseState(); + +// View last valid offer id +const result = await dataNftMarket.viewLastValidOfferId(); + +// Create addOffer transaction +const result = dataNftMarket.addOffer(new Address(''), '', 0, 0, '', 0, 0, 0); + +// Create acceptOffer transaction +const result = dataNftMarket.acceptOffer(new Address(''), 0, 0, 0); + +// Create cancelOffer transaction +const result = dataNftMarket.cancelOffer(new Address(''), 0); + +// Create cancelOffer transaction without sending the funds back to the owner +const result = dataNftMarket.cancelOffer(new Address(''), 0, false); + +// Create withdrawFromCancelledOffer transaction +const result = dataNftMarket.withdrawCancelledOffer(new Address(''), 0); + +// Create changeOfferPrice transaction +const result = dataNftMarket.changeOfferPrice(new Address(''), 0, 0); +``` + ### Traits structure Items below marked "required" are the "minimum" required for it to be compatible with the Itheum protocol. You can add any additional traits you may need for your own reasons. diff --git a/src/minter.ts b/src/minter.ts index 33d039d..a59aa13 100644 --- a/src/minter.ts +++ b/src/minter.ts @@ -34,7 +34,7 @@ export abstract class Minter { protected constructor( env: string, - contractAddress: string, + contractAddress: IAddress, abiFile: any, timeout: number = 10000 ) { @@ -54,7 +54,7 @@ export abstract class Minter { } ); this.contract = new SmartContract({ - address: new Address(contractAddress), + address: contractAddress, abi: AbiRegistry.create(abiFile) }); } diff --git a/src/nft-minter.ts b/src/nft-minter.ts index c967183..b3aba84 100644 --- a/src/nft-minter.ts +++ b/src/nft-minter.ts @@ -33,7 +33,7 @@ export class NftMinter extends Minter { * @param contractAddress The address of the factory generated smart contract * @param timeout Timeout for the network provider (DEFAULT = 10000ms) */ - constructor(env: string, contractAddress: string, timeout: number = 10000) { + constructor(env: string, contractAddress: IAddress, timeout: number = 10000) { super(env, contractAddress, dataNftLeaseAbi, timeout); } @@ -143,7 +143,7 @@ export class NftMinter extends Minter { * * NOTE: The `dataStreamUrl` is being encrypted and the `media` and `metadata` urls are build and uploaded to IPFS * - * NOTE: The `options.nftStorageToken` is required when not using custom image and traits, when using custom image and traits the traits should be compliant with the `traits` structure + * NOTE: The `options.nftStorageToken` is required when not using custom image and traits, when using custom image and traits the traits should be compliant with the [Traits](https://github.com/Itheum/sdk-mx-data-nft#traits-structure) structure * * For more information, see the [README documentation](https://github.com/Itheum/sdk-mx-data-nft#create-a-mint-transaction). * @@ -159,7 +159,7 @@ export class NftMinter extends Minter { * - imageUrl: the URL of the image for the Data NFT * - traitsUrl: the URL of the traits for the Data NFT * - nftStorageToken: the nft storage token to be used to upload the image and metadata to IPFS - * - antiSpamTokenIdentifier: the anti spam token identifier to be used for the minting (default = `ITHEUM` token identifier based on the {@link EnvironmentsEnum}) + * - antiSpamTokenIdentifier: the anti spam token identifier to be used for the minting * - antiSpamTax: the anti spam tax to be set for the Data NFT-FT with decimals. Needs to be greater than 0 and should be obtained in real time via {@link viewMinterRequirements} prior to calling mint. */ async mint( diff --git a/src/sft-minter.ts b/src/sft-minter.ts index aa24a43..99604fb 100644 --- a/src/sft-minter.ts +++ b/src/sft-minter.ts @@ -1,4 +1,5 @@ import { + Address, AddressValue, BigUIntValue, ContractCallPayloadBuilder, @@ -37,7 +38,7 @@ export class SftMinter extends Minter { constructor(env: string, timeout: number = 10000) { super( env, - minterContractAddress[env as EnvironmentsEnum], + new Address(minterContractAddress[env as EnvironmentsEnum]), dataNftMinterAbi, timeout ); diff --git a/tests/nftminter.test.ts b/tests/nftminter.test.ts new file mode 100644 index 0000000..35a74a4 --- /dev/null +++ b/tests/nftminter.test.ts @@ -0,0 +1,121 @@ +import { Address, Transaction } from '@multiversx/sdk-core/out'; +import { NftMinter } from '../src'; + +describe('Nft minter test', () => { + test('#initialize minter', async () => { + const factoryGeneratedContract = new Address( + 'erd1qqqqqqqqqqqqqpgqpd9qxrq5a03jrneafmlmckmlj5zgdj55fsxsqa7jsm' + ); + const nftMinter = new NftMinter('devnet', factoryGeneratedContract); + + expect(nftMinter).toBeInstanceOf(NftMinter); + }); + + test('#initialize minter contract transaction', async () => { + const factoryGeneratedContract = new Address( + 'erd1qqqqqqqqqqqqqpgqpd9qxrq5a03jrneafmlmckmlj5zgdj55fsxsqa7jsm' + ); + const nftMinter = new NftMinter('devnet', factoryGeneratedContract); + + const adminOfContract = new Address( + 'erd1qqqqqqqqqqqqqpgqpd9qxrq5a03jrneafmlmckmlj5zgdj55fsxsqa7jsm' + ); + + const initTx = nftMinter.initializeContract( + adminOfContract, + 'Collection-Name-To-Mint', + 'CollectionTicker', + 0, + false, + new Address( + 'erd1qqqqqqqqqqqqqpgqpd9qxrq5a03jrneafmlmckmlj5zgdj55fsxsqa7jsm' + ) + ); + expect(initTx).toBeInstanceOf(Transaction); + }); + + test('#mint nft using itheum generated image', async () => { + const factoryGeneratedContract = new Address( + 'erd1qqqqqqqqqqqqqpgqpd9qxrq5a03jrneafmlmckmlj5zgdj55fsxsqa7jsm' + ); + const nftMinter = new NftMinter('devnet', factoryGeneratedContract); + + const senderAddress = new Address( + 'erd1qqqqqqqqqqqqqpgqpd9qxrq5a03jrneafmlmckmlj5zgdj55fsxsqa7jsm' + ); + + const mintTx = await nftMinter.mint( + senderAddress, + 'TokenName', + 'https://d37x5igq4vw5mq.cloudfront.net/datamarshalapi/achilles/v1', + 'https://raw.githubusercontent.com/Itheum/data-assets/main/Health/H1__Signs_of_Anxiety_in_American_Households_due_to_Covid19/dataset.json', + 'https://itheumapi.com/programReadingPreview/70dc6bd0-59b0-11e8-8d54-2d562f6cba54', + 1000, + 'Title for token', + 'Description for token', + { + nftStorageToken: + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkaWQ6ZXRocjoweDMzQjZGNzhmOTZmZjVmMGIwMUJFNzJmZTQ0NDRmMjBCYzhkOEQ0REUiLCJpc3MiOiJuZnQtc3RvcmFnZSIsImlhdCI6MTY5MTc0NDc5NDY5MCwibmFtZSI6InRlc3QifQ.lTjq16CgrDipiVClOrbWNt0A0zYkJ9YGVeDz1TlGqQ0' + } + ); + expect(mintTx).toBeInstanceOf(Transaction); + }, 20000); + + test('#mint nft using your image and metadata', async () => { + const factoryGeneratedContract = new Address( + 'erd1qqqqqqqqqqqqqpgqpd9qxrq5a03jrneafmlmckmlj5zgdj55fsxsqa7jsm' + ); + const nftMinter = new NftMinter('devnet', factoryGeneratedContract); + + const senderAddress = new Address( + 'erd1qqqqqqqqqqqqqpgqpd9qxrq5a03jrneafmlmckmlj5zgdj55fsxsqa7jsm' + ); + + const mintTx = await nftMinter.mint( + senderAddress, + 'TokenName', + 'https://d37x5igq4vw5mq.cloudfront.net/datamarshalapi/achilles/v1', + 'https://raw.githubusercontent.com/Itheum/data-assets/main/Health/H1__Signs_of_Anxiety_in_American_Households_due_to_Covid19/dataset.json', + 'https://itheumapi.com/programReadingPreview/70dc6bd0-59b0-11e8-8d54-2d562f6cba54', + 1000, + 'Title for token', + 'Description for token', + { + imageUrl: + 'https://ipfs.io/ipfs/bafybeih7bvpcfj42nawm7g4bkbu25cqxbhlzth5sxm6qjwis3tke23p7ty/image.png', + traitsUrl: + 'https://ipfs.io/ipfs/bafybeih7bvpcfj42nawm7g4bkbu25cqxbhlzth5sxm6qjwis3tke23p7ty/metadata.json' + } + ); + expect(mintTx).toBeInstanceOf(Transaction); + }, 20000); + + test('#mint nft using tax for minting', async () => { + const factoryGeneratedContract = new Address( + 'erd1qqqqqqqqqqqqqpgqpd9qxrq5a03jrneafmlmckmlj5zgdj55fsxsqa7jsm' + ); + const nftMinter = new NftMinter('devnet', factoryGeneratedContract); + + const senderAddress = new Address( + 'erd1qqqqqqqqqqqqqpgqpd9qxrq5a03jrneafmlmckmlj5zgdj55fsxsqa7jsm' + ); + const mintTx = await nftMinter.mint( + senderAddress, + 'TokenName', + 'https://d37x5igq4vw5mq.cloudfront.net/datamarshalapi/achilles/v1', + 'https://raw.githubusercontent.com/Itheum/data-assets/main/Health/H1__Signs_of_Anxiety_in_American_Households_due_to_Covid19/dataset.json', + 'https://itheumapi.com/programReadingPreview/70dc6bd0-59b0-11e8-8d54-2d562f6cba54', + 1000, + 'Title for token', + 'Description for token', + { + nftStorageToken: + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkaWQ6ZXRocjoweDMzQjZGNzhmOTZmZjVmMGIwMUJFNzJmZTQ0NDRmMjBCYzhkOEQ0REUiLCJpc3MiOiJuZnQtc3RvcmFnZSIsImlhdCI6MTY5MTc0NDc5NDY5MCwibmFtZSI6InRlc3QifQ.lTjq16CgrDipiVClOrbWNt0A0zYkJ9YGVeDz1TlGqQ0', + antiSpamTax: 1000000000000000000, + antiSpamTokenIdentifier: 'EGLD' + } + ); + + expect(mintTx).toBeInstanceOf(Transaction); + }); +});