Skip to content

Commit

Permalink
feature: logic and error handling improvements to CNftSolMinter
Browse files Browse the repository at this point in the history
  • Loading branch information
newbreedofgeek committed Sep 13, 2024
1 parent 025e79f commit fe60bf3
Show file tree
Hide file tree
Showing 4 changed files with 123 additions and 101 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@itheum/sdk-mx-data-nft",
"version": "3.7.0-alpha.1",
"version": "3.7.0-alpha.2",
"description": "SDK for Itheum's Data NFT Technology on MultiversX and Solana",
"main": "out/index.js",
"types": "out/index.d.js",
Expand Down
211 changes: 111 additions & 100 deletions src/cnft-sol-minter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { checkTraitsUrl, checkUrlIsUp } from './common/utils';
import { ErrArgumentNotSet } from './errors';
import { MinterSol } from './minter-sol';
import { StringValidator, validateResults } from './common/validator';
import { CNftSolPostMintMetaType } from './interfaces';

export class CNftSolMinter extends MinterSol {
/**
Expand All @@ -25,8 +26,6 @@ export class CNftSolMinter extends MinterSol {
*
* 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
*
* For more information, see the [README documentation](https://github.com/Itheum/sdk-mx-data-nft#create-a-mint-transaction).
*
* @param creatorAddress the address of the creator who we mint a CNft for
* @param tokenName the name of the DataNFT-FT. Between 3 and 20 alphanumeric characters, no spaces.
* @param dataMarshalUrl the url of the data marshal. A live HTTPS URL that returns a 200 OK HTTP code.
Expand Down Expand Up @@ -59,7 +58,11 @@ export class CNftSolMinter extends MinterSol {
imgGenBg?: string;
imgGenSet?: string;
}
): Promise<{ imageUrl: string; metadataUrl: string; mintMeta: object }> {
): Promise<{
imageUrl: string;
metadataUrl: string;
mintMeta: CNftSolPostMintMetaType;
}> {
const {
imageUrl,
traitsUrl,
Expand Down Expand Up @@ -105,117 +108,125 @@ export class CNftSolMinter extends MinterSol {
let imageOnIpfsUrl: string;
let metadataOnIpfsUrl: string;

const { dataNftHash, dataNftStreamUrlEncrypted } =
await dataNFTDataStreamAdvertise(
dataStreamUrl,
dataMarshalUrl,
creatorAddress // the caller is the Creator
);

if (!imageUrl) {
if (!nftStorageToken) {
throw new ErrArgumentNotSet(
'nftStorageToken',
'NFT Storage token is required when not using custom image and traits'
// handle all logic related to data stream and ipfs gen of img,traits etc
let allDataStreamAndIPFSLogicDone = false;

try {
const { dataNftHash, dataNftStreamUrlEncrypted } =
await dataNFTDataStreamAdvertise(
dataStreamUrl,
dataMarshalUrl,
creatorAddress // the caller is the Creator
);
}

// create the img generative service API based on user options
let imgGenServiceApi = `${this.imageServiceUrl}/v1/generateNFTArt?hash=${dataNftHash}`;
if (!imageUrl) {
if (!nftStorageToken) {
throw new ErrArgumentNotSet(
'nftStorageToken',
'NFT Storage token is required when not using custom image and traits'
);
}

if (imgGenBg && imgGenBg.trim() !== '') {
imgGenServiceApi += `&bg=${imgGenBg.trim()}`;
}
// create the img generative service API based on user options
let imgGenServiceApi = `${this.imageServiceUrl}/v1/generateNFTArt?hash=${dataNftHash}`;

if (imgGenSet && imgGenSet.trim() !== '') {
imgGenServiceApi += `&set=${imgGenSet.trim()}`;
}
if (imgGenBg && imgGenBg.trim() !== '') {
imgGenServiceApi += `&bg=${imgGenBg.trim()}`;
}

let resImgCall: any = '';
let dataImgCall: any = '';
let _imageFile: Blob = new Blob();

resImgCall = await fetch(imgGenServiceApi);
dataImgCall = await resImgCall.blob();
_imageFile = dataImgCall;

const traitsFromImgHeader = resImgCall.headers.get('x-nft-traits') || '';

const { imageOnIpfsUrl: imgOnIpfsUrl } = await storeToIpfsOnlyImg(
nftStorageToken,
_imageFile
);

const cNftMetadataContent = createIpfsMetadataSolCNft(
tokenName,
datasetTitle,
datasetDescription,
imgOnIpfsUrl,
creatorAddress,
dataNftStreamUrlEncrypted,
dataPreviewUrl,
dataMarshalUrl,
traitsFromImgHeader,
extraAssets ?? []
);

const { metadataIpfsUrl } = await storeToIpfsFullSolCNftMetadata(
nftStorageToken,
cNftMetadataContent
);

imageOnIpfsUrl = imgOnIpfsUrl;
metadataOnIpfsUrl = metadataIpfsUrl;
} else {
if (!traitsUrl) {
throw new ErrArgumentNotSet(
'traitsUrl',
'Traits URL is required when using custom image'
if (imgGenSet && imgGenSet.trim() !== '') {
imgGenServiceApi += `&set=${imgGenSet.trim()}`;
}

let resImgCall: any = '';
let dataImgCall: any = '';
let _imageFile: Blob = new Blob();

resImgCall = await fetch(imgGenServiceApi);
dataImgCall = await resImgCall.blob();
_imageFile = dataImgCall;

const traitsFromImgHeader =
resImgCall.headers.get('x-nft-traits') || '';

const { imageOnIpfsUrl: imgOnIpfsUrl } = await storeToIpfsOnlyImg(
nftStorageToken,
_imageFile
);
}

await checkTraitsUrl(traitsUrl);
const cNftMetadataContent = createIpfsMetadataSolCNft(
tokenName,
datasetTitle,
datasetDescription,
imgOnIpfsUrl,
creatorAddress,
dataNftStreamUrlEncrypted,
dataPreviewUrl,
dataMarshalUrl,
traitsFromImgHeader,
extraAssets ?? []
);

imageOnIpfsUrl = imageUrl;
metadataOnIpfsUrl = traitsUrl;
}
const { metadataIpfsUrl } = await storeToIpfsFullSolCNftMetadata(
nftStorageToken,
cNftMetadataContent
);

// we not make a call to our private cNFt minter API
let mintMeta: any = {};
imageOnIpfsUrl = imgOnIpfsUrl;
metadataOnIpfsUrl = metadataIpfsUrl;
} else {
if (!traitsUrl) {
throw new ErrArgumentNotSet(
'traitsUrl',
'Traits URL is required when using custom image'
);
}

try {
const postHeaders = new Headers();
postHeaders.append('Content-Type', 'application/json');

const raw = JSON.stringify({
metadataOnIpfsUrl,
tokenName,
mintForSolAddr: creatorAddress,
solSignature: 'solSignature',
signatureNonce: 'signatureNonce'
});

const requestOptions = {
method: 'POST',
headers: postHeaders,
body: raw
};

let resMintCall: any = '';
let dataMintCall: any = '';

resMintCall = await fetch(this.solCNftMinterServiceUrl, requestOptions);
dataMintCall = await resMintCall.text();
mintMeta = dataMintCall;

// .then((response) => response.text())
// .then((result) => console.log(result))
// .catch((error) => console.error(error));
await checkTraitsUrl(traitsUrl);

imageOnIpfsUrl = imageUrl;
metadataOnIpfsUrl = traitsUrl;
}

allDataStreamAndIPFSLogicDone = true;
} catch (e: any) {
mintMeta = { error: true, errMsg: e.toString() };
throw e;
}

// we not make a call to our private cNFt minter API
let mintMeta: CNftSolPostMintMetaType = {};

if (allDataStreamAndIPFSLogicDone) {
try {
const postHeaders = new Headers();
postHeaders.append('Content-Type', 'application/json');

const raw = JSON.stringify({
metadataOnIpfsUrl,
tokenName,
mintForSolAddr: creatorAddress,
solSignature: 'solSignature',
signatureNonce: 'signatureNonce'
});

const requestOptions = {
method: 'POST',
headers: postHeaders,
body: raw
};

let resMintCall: any = '';
let dataMintCall: any = '';

resMintCall = await fetch(this.solCNftMinterServiceUrl, requestOptions);
dataMintCall = await resMintCall.text();
mintMeta = dataMintCall;
} catch (e: any) {
mintMeta = { error: true, errMsg: e.toString() };
throw e;
}
}

return {
imageUrl: imageOnIpfsUrl,
metadataUrl: metadataOnIpfsUrl,
Expand Down
1 change: 1 addition & 0 deletions src/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export class ErrArgumentNotSet extends Error {
super(`Argument "${argument}" is not set. ${message}`);
}
}

export class ErrInvalidArgument extends Error {
public constructor(message: string) {
super(`Invalid argument: ${message}`);
Expand Down
10 changes: 10 additions & 0 deletions src/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ export enum NftEnumType {
SemiFungibleESDT = 'SemiFungibleESDT',
MetaESDT = 'MetaESDT'
}

export interface MarketplaceRequirements {
acceptedTokens: string[];
acceptedPayments: string[];
Expand Down Expand Up @@ -234,3 +235,12 @@ export interface UserData {
accumulatedRewardsBypass: BigNumber.Value;
vaultNonce: number;
}

export type CNftSolPostMintMetaType = {
error?: boolean;
errMsg?: string;
assetId?: string;
leafSchema?: any;
index?: number;
root?: any;
};

0 comments on commit fe60bf3

Please sign in to comment.