Skip to content

Commit

Permalink
Merge pull request #41 from dimitrov-d/master
Browse files Browse the repository at this point in the history
Add support for Unique NFTs
  • Loading branch information
dimitrov-d authored Dec 17, 2024
2 parents 5a5de86 + 4cea141 commit de4b8cb
Show file tree
Hide file tree
Showing 6 changed files with 159 additions and 7 deletions.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

33 changes: 33 additions & 0 deletions packages/sdk/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,39 @@ const substrateCollection = await nft.createSubstrate({
...
});

// or create a unique collection
const uniqueCollection = await nft.createUnique({
collectionType: CollectionType.GENERIC,
chain: SubstrateChain.UNIQUE,
name: 'UniqueArtworks',
symbol: 'UA',
description: 'A collection of one-of-a-kind digital artworks.',
isRevokable: false,
isSoulbound: false,
metadata: {
'1': {
name: 'Unique NFT 1',
description: 'Description for Unique NFT 1',
image: 'https://example.com/nft1.png',
attributes: {
trait_type: 'color',
value: 'red',
display_type: 'string',
},
},
'2': {
name: 'Unique NFT 2',
description: 'Description for Unique NFT 2',
image: 'https://example.com/nft2.png',
attributes: {
trait_type: 'color',
value: 'blue',
display_type: 'string',
},
},
},
});

// check if collection is deployed - available on chain
if (collection.collectionStatus == CollectionStatus.DEPLOYED) {
console.log('Collection deployed: ', collection.transactionHash);
Expand Down
2 changes: 1 addition & 1 deletion packages/sdk/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@apillon/sdk",
"description": "▶◀ Apillon SDK for NodeJS ▶◀",
"version": "3.7.0",
"version": "3.8.0",
"author": "Apillon",
"license": "MIT",
"main": "./dist/index.js",
Expand Down
18 changes: 14 additions & 4 deletions packages/sdk/src/modules/nft/nft.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
ICreateCollection,
ICreateSubstrateCollection,
ICreateCollectionBase,
ICreateUniqueCollection,
} from '../../types/nfts';
import { NftCollection } from './nft-collection';

Expand Down Expand Up @@ -52,7 +53,7 @@ export class Nft extends ApillonModule {
* @returns A NftCollection instance.
*/
public async create(data: ICreateCollection) {
return await this.createNft(data, true);
return await this.createNft(data, 'evm');
}

/**
Expand All @@ -61,17 +62,26 @@ export class Nft extends ApillonModule {
* @returns A NftCollection instance.
*/
public async createSubstrate(data: ICreateSubstrateCollection) {
return await this.createNft(data, false);
return await this.createNft(data, 'substrate');
}

private async createNft(data: ICreateCollectionBase, isEvm: boolean) {
/**
* Deploys a new Unique NftCollection smart contract.
* @param data NFT collection data.
* @returns A NftCollection instance.
*/
public async createUnique(data: ICreateUniqueCollection) {
return await this.createNft(data, 'unique');
}

private async createNft(data: ICreateCollectionBase, type: string) {
// If not drop, set drop properties to default 0
if (!data.drop) {
data.dropStart = data.dropPrice = data.dropReserve = 0;
}
const response = await ApillonApi.post<
NftCollection & { collectionUuid: string }
>(`${this.API_PREFIX}/${isEvm ? 'evm' : 'substrate'}`, data);
>(`${this.API_PREFIX}/${type}`, data);
return new NftCollection(response.collectionUuid, response);
}
}
43 changes: 43 additions & 0 deletions packages/sdk/src/tests/nft.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,49 @@ describe('Nft tests', () => {
expect(collection.isSoulbound).toEqual(false);
});

test.only('creates a new unique collection', async () => {
const uniqueCollectionData = {
...nftData,
maxSupply: 1000,
isRevokable: true,
isSoulbound: false,
metadata: {
'1': {
name: 'Unique NFT 1',
description: 'Description for Unique NFT 1',
image: 'https://example.com/nft1.png',
attributes: {
value: 'Attribute Value 1',
trait_type: 'Attribute Type 1',
display_type: 'string',
},
},
'2': {
name: 'Unique NFT 2',
description: 'Description for Unique NFT 2',
image: 'https://example.com/nft2.png',
attributes: {
value: 'Attribute Value 2',
trait_type: 'Attribute Type 2',
display_type: 'string',
},
},
},
};

const collection = await nft.createUnique(uniqueCollectionData);
expect(collection.uuid).toBeDefined();
expect(collection.contractAddress).toBeDefined();
expect(collection.symbol).toEqual('SDKT');
expect(collection.name).toEqual('SDK Test');
expect(collection.description).toEqual('Created from SDK tests');
expect(collection.isAutoIncrement).toEqual(true);
expect(collection.isRevokable).toEqual(true);
expect(collection.isSoulbound).toEqual(false);

collectionUuid = collection.uuid;
});

test('mints a new nft', async () => {
const collection = nft.collection(collectionUuid);
const res = await collection.mint({
Expand Down
66 changes: 66 additions & 0 deletions packages/sdk/src/types/nfts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export enum EvmChain {

export enum SubstrateChain {
ASTAR = 8,
UNIQUE = 11,
}

export enum CollectionStatus {
Expand Down Expand Up @@ -57,16 +58,81 @@ export interface ICreateCollectionBase {
}

export interface ICreateCollection extends ICreateCollectionBase {
/**
* Indicates if the collection is revokable (burnable).
*/
isRevokable: boolean;
/**
* Indicates if the collection is soulbound.
*/
isSoulbound: boolean;
/**
* If enabled, newly minted NFTs will have token IDs in sequential order.
*/
isAutoIncrement?: boolean;
/**
* The EVM chain on which the collection will be deployed.
*/
chain: EvmChain;
}

export interface ICreateSubstrateCollection extends ICreateCollectionBase {
chain: SubstrateChain;
}

export interface IMetadataAttributes {
/**
* Trait value.
*/
value: string;
/**
* Name of the trait.
*/
trait_type: string;
/**
* Type for displaying trait (number, date,...).
*/
display_type: string;
}

export interface IMetadata {
/**
* NFT name.
*/
name: string;
/**
* NFT description.
*/
description: string;
/**
* NFT image URL.
*/
image: string;
/**
* Array of NFT attributes.
*/
attributes: IMetadataAttributes;
}

export interface ICreateUniqueCollection extends ICreateCollectionBase {
/**
* Maximum supply of the collection.
*/
maxSupply: number;
/**
* For revokable collection owner can destroy (burn) NFTs at any time.
*/
isRevokable: boolean;
/**
* Soulbound tokens are NFTs that are bound to wallet and not transferable. (default: false)
*/
isSoulbound: boolean;
/**
* Object containing metadata for different token ids.
*/
metadata: { [tokenId: string]: IMetadata };
}

export interface ITransaction {
chainId: number;
transactionType: TransactionType;
Expand Down

0 comments on commit de4b8cb

Please sign in to comment.