Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feat] improve AINFT object #302

Merged
merged 2 commits into from
Jul 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 50 additions & 20 deletions src/ainft721Object.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { AinftToken } from "./ainftToken";
import FactoryBase from "./factoryBase";
import { HttpMethod } from "./types";
import Ain from "@ainblockchain/ain-js";
import { AinftToken } from './ainftToken';
import FactoryBase from './factoryBase';
import { HttpMethod, Metadata } from './types';
import Ain from '@ainblockchain/ain-js';

/**
* The class of AINFT 721 object.
Expand All @@ -17,6 +17,10 @@ export default class Ainft721Object extends FactoryBase {
readonly owner: string;
/** The ID of app in AIN blockchain. */
readonly appId: string;
/** The description of AINFT object. */
readonly description?: string | null;
/** The metadata of AINFT object. */
readonly metadata?: Metadata;

/**
* Constructor of Ainft721Object.
Expand All @@ -29,13 +33,26 @@ export default class Ainft721Object extends FactoryBase {
* @param ain Ain instance to sign and send transaction to AIN blockchain.
* @param baseUrl The base url to request api to AINFT factory server.
*/
constructor(objectInfo: { id: string, name: string, symbol: string, owner: string}, ain: Ain, baseUrl: string) {
constructor(
objectInfo: {
id: string;
name: string;
symbol: string;
owner: string;
description?: string;
metadata?: Metadata;
},
ain: Ain,
baseUrl: string
) {
super(baseUrl, null, ain);
this.id = objectInfo.id;
this.name = objectInfo.name;
this.symbol = objectInfo.symbol;
this.owner = objectInfo.owner;
this.appId = Ainft721Object.getAppId(objectInfo.id);
this.description = objectInfo.description || null;
this.metadata = objectInfo.metadata || {};
}

/**
Expand All @@ -44,7 +61,7 @@ export default class Ainft721Object extends FactoryBase {
* @returns Returns AINFT token instance.
* ```ts
* import AinftJs from '@ainft-team/ainft-js';
*
*
* const ainftJs = new AinftJs('YOUR-PRIVATE-KEY');
* async function main() {
* const ainftObject = await ainftJs.nft.get('YOUR-AINFT-OBJECT-ID');
Expand All @@ -53,12 +70,25 @@ export default class Ainft721Object extends FactoryBase {
* ```
*/
async getToken(tokenId: string): Promise<AinftToken> {
const { nfts } = await this.sendRequestWithoutSign(HttpMethod.GET, `native/search/nfts`, { ainftObjectId: this.id, tokenId });
const { nfts } = await this.sendRequestWithoutSign(
HttpMethod.GET,
`native/search/nfts`,
{ ainftObjectId: this.id, tokenId }
);
if (nfts.length === 0) {
throw new Error('Token not found');
}
const token = nfts[0];
return new AinftToken({ ainftObjectId: this.id, tokenId, tokenURI: token.tokenURI, metadata: token.metadata }, this.ain, this.baseUrl);
return new AinftToken(
{
ainftObjectId: this.id,
tokenId,
tokenURI: token.tokenURI,
metadata: token.metadata,
},
this.ain,
this.baseUrl
);
}

/**
Expand All @@ -67,10 +97,10 @@ export default class Ainft721Object extends FactoryBase {
* @param to The address the AINFT will be send to.
* @param tokenId Token ID of AINFT.
* @returns Returns transaction result.
*
*
* ```ts
* import AinftJs from '@ainft-team/ainft-js';
*
*
* const ainftJs = new AinftJs('YOUR-PRIVATE-KEY');
* async function main() {
* const ainftObject = await ainftJs.nft.get('YOUR-AINFT-OBJECT-ID');
Expand All @@ -80,7 +110,7 @@ export default class Ainft721Object extends FactoryBase {
* ```
*/
async transfer(from: string, to: string, tokenId: string): Promise<any> {
const txbody = await this.getTxBodyForTransfer(from, to, tokenId);
const txbody = await this.getTxBodyForTransfer(from, to, tokenId);
return this.ain.sendTransaction(txbody);
}

Expand All @@ -91,7 +121,7 @@ export default class Ainft721Object extends FactoryBase {
* @returns Returns transaction result.
* ```ts
* import AinftJs from '@ainft-team/ainft-js';
*
*
* const ainftJs = new AinftJs('YOUR-PRIVATE-KEY');
* async function main() {
* const ainftObject = await ainftJs.nft.get('YOUR-AINFT-OBJECT-ID');
Expand All @@ -112,10 +142,10 @@ export default class Ainft721Object extends FactoryBase {
* @param to The address the AINFT will be send to.
* @param tokenId Token ID of AINFT.
* @returns Returns transaction body without signature.
*
*
* ```ts
* import AinftJs from '@ainft-team/ainft-js';
*
*
* const ainftJs = new AinftJs('YOUR-PRIVATE-KEY');
* async function main() {
* const ainftObject = await ainftJs.nft.get('YOUR-AINFT-OBJECT-ID');
Expand All @@ -128,7 +158,7 @@ export default class Ainft721Object extends FactoryBase {
const body = {
address: from,
toAddress: to,
}
};
const trailingUrl = `native/${this.id}/${tokenId}/transfer`;
return this.sendRequest(HttpMethod.POST, trailingUrl, body);
}
Expand All @@ -139,10 +169,10 @@ export default class Ainft721Object extends FactoryBase {
* @param to The address the AINFT will be send.
* @param tokenId Token ID of AINFT.
* @returns Returns transaction body without signature.
*
*
* ```ts
* import AinftJs from '@ainft-team/ainft-js';
*
*
* const ainftJs = new AinftJs('YOUR-PRIVATE-KEY');
* async function main() {
* const ainftObject = await ainftJs.nft.get('YOUR-AINFT-OBJECT-ID');
Expand All @@ -156,16 +186,16 @@ export default class Ainft721Object extends FactoryBase {
address: ownerAddress,
toAddress: to,
tokenId,
}
};
const trailingUrl = `native/${this.id}/mint`;
return this.sendRequest(HttpMethod.POST, trailingUrl, body);
}

/**
* Gets app ID by AINFT object ID.
* @param id
* @param id
*/
static getAppId(objectId: string): string {
return `ainft721_${objectId.toLowerCase()}`;
}
}
}
7 changes: 5 additions & 2 deletions src/nft.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import _ from 'lodash';

import FactoryBase from './factoryBase';
import {
DeleteAssetParams,
Expand All @@ -7,6 +9,7 @@ import {
UploadAssetFromDataUrlParams,
AinftTokenSearchResponse,
AinftObjectSearchResponse,
AinftObjectCreateParams,
} from './types';
import Ainft721Object from './ainft721Object';
import stringify from 'fast-json-stable-stringify';
Expand Down Expand Up @@ -38,15 +41,15 @@ export default class Nft extends FactoryBase {
* });
* ```
*/
async create(name: string, symbol: string, description?: string, metadata?: object): Promise<{ txHash: string; ainftObject: Ainft721Object }> {
async create({ name, symbol, description, metadata }: AinftObjectCreateParams): Promise<{ txHash: string; ainftObject: Ainft721Object }> {
const address = await this.ain.signer.getAddress();

const body = {
address,
name,
symbol,
...(description && { description }),
...(metadata && { metadata }),
...(metadata && !_.isEmpty(metadata) && { metadata }),
};
const trailingUrl = 'native';
const { ainftObjectId, txBody } = await this.sendRequest(HttpMethod.POST, trailingUrl, body);
Expand Down
22 changes: 19 additions & 3 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1021,6 +1021,7 @@ export interface SearchOption {
limit?: number,
cursor?: string,
}

export interface NftSearchParams extends SearchOption {
/** The address of the user who owns the AINFT. */
userAddress?: string;
Expand Down Expand Up @@ -1091,7 +1092,7 @@ export interface getTxbodyAddAiHistoryParams {

export interface AddAiHistoryParams extends Omit<getTxbodyAddAiHistoryParams, 'userAddress'> {}

export interface AinftObjectSearchResponse extends SearchReponse {
export interface AinftObjectSearchResponse extends SearchResponse {
ainftObjects: {
id: string;
name: string;
Expand All @@ -1100,7 +1101,7 @@ export interface AinftObjectSearchResponse extends SearchReponse {
}[];
}

export interface AinftTokenSearchResponse extends SearchReponse {
export interface AinftTokenSearchResponse extends SearchResponse {
nfts: {
tokenId: string;
owner: string;
Expand All @@ -1110,11 +1111,26 @@ export interface AinftTokenSearchResponse extends SearchReponse {
}[];
}

export interface SearchReponse {
export interface SearchResponse {
isFinal: boolean;
cursor?: string;
}

export interface Metadata {
[key: string]: any;
}

export interface AinftObjectCreateParams {
/** The name of the AINFT object. */
name: string;
/** The symbol of the AINFT object. */
symbol: string;
/** The description of the AINFT object. */
description?: string | null;
/** The metadata of the AINFT object. */
metadata?: Metadata | null;
}

export enum ServiceType {
CHAT = 'chat',
}
Expand Down
1 change: 1 addition & 0 deletions test/constants.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export const TX_HASH_REGEX = /^0x([A-Fa-f0-9]{64})$/;
export const AINFT_OBJECT_REGEX = /^0x([A-Fa-f0-9]{40})$/;
export const ASSISTANT_REGEX = /^asst_([A-Za-z0-9]{24})$/;
export const THREAD_REGEX = /^thread_([A-Za-z0-9]{24})$/;
export const MESSAGE_REGEX = /^msg_([A-Za-z0-9]{24})$/;
45 changes: 45 additions & 0 deletions test/nft.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import AinftJs from '../src/ainft';
import { AINFT_OBJECT_REGEX, TX_HASH_REGEX } from './constants';
import { address, privateKey } from './test_data';

describe('nft', () => {
const ainft = new AinftJs({
privateKey,
baseUrl: 'https://ainft-api-dev.ainetwork.ai',
blockchainUrl: 'https://testnet-api.ainetwork.ai',
chainId: 0,
});

it('should create ainft object', async () => {
const result = await ainft.nft.create({
name: 'name',
symbol: 'symbol',
description: 'description',
metadata: {
author: {
address: address,
username: 'username',
},
logoImage: 'https://picsum.photos/200/200',
bannerImage: 'https://picsum.photos/1400/264',
externalLink: 'https://example.com',
},
});

expect(result.txHash).toMatch(TX_HASH_REGEX);
expect(result.ainftObject.id).toMatch(AINFT_OBJECT_REGEX);
expect(result.ainftObject.name).toBe('name');
expect(result.ainftObject.symbol).toBe('symbol');
expect(result.ainftObject.owner).toBe(address);
expect(result.ainftObject.description).toBe('description');
expect(result.ainftObject.metadata).toEqual({
author: {
address: address,
username: 'username',
},
logoImage: 'https://picsum.photos/200/200',
bannerImage: 'https://picsum.photos/1400/264',
externalLink: 'https://example.com',
});
});
});
Loading