Repository: alchemyplatform/alchemy-sdk-js
Pull request #25 (2022-06-08 18:03:07)

Support array types in NFT descriptions
Some NFTs have a their `description` fields as an array. The SDK should handle this appropriately and join the array as a string.

Example contract: `0x0075ce3f8d2cecae84600d4a1f8675a72819896d`



Patch:
diff --git a/README.md b/README.md
index e77e8a74..337372a9 100644
--- a/README.md
+++ b/README.md
@@ -3,7 +3,7 @@
 Alchemy SDK helps developers use Alchemy's APIs and endpoints more efficiently. This is a lightweight, modular SDK
 that encapsulates common usage patterns and abstracts away the complexities of both our HTTP and JSON-RPC endpoints.
 
-Note that the SDK is still in private beta and is not published in NPM. Alchemy reserves the right to (and almost certainly will) make breaking
+Note that the SDK is still in public beta. Alchemy reserves the right to (and almost certainly will) make breaking
 API changes in subsequent releases (don't write production code around it just yet).
 
 ## Getting started
@@ -185,7 +185,10 @@ getNftsForOwner(alchemy, '0xshah.eth', {
 Getting all the owners of the BAYC NFT.
 
 ```ts
-import { getOwnersForNft, getNftsForCollectionIterator } from '@alch/alchemy-sdk';
+import {
+  getOwnersForNft,
+  getNftsForCollectionIterator
+} from '@alch/alchemy-sdk';
 
 // Bored Ape Yacht Club contract address.
 const baycAddress = '0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D';
diff --git a/src/api/nft.ts b/src/api/nft.ts
index 0e1726ae..e726a86f 100644
--- a/src/api/nft.ts
+++ b/src/api/nft.ts
@@ -35,13 +35,13 @@ export class BaseNft {
   }
 
   /** @internal */
-  static fromResponse(ownedNft: RawBaseNft, contractAddress: string): BaseNft {
+  static fromResponse(baseNft: RawBaseNft, contractAddress: string): BaseNft {
     return new BaseNft(
       contractAddress,
       // We have to normalize the token id here since the backend sometimes
       // returns the token ID as a hex string and sometimes as an integer.
-      BigNumber.from(ownedNft.id.tokenId).toString(),
-      ownedNft.id.tokenMetadata?.tokenType ?? NftTokenType.UNKNOWN
+      BigNumber.from(baseNft.id.tokenId).toString(),
+      baseNft.id.tokenMetadata?.tokenType ?? NftTokenType.UNKNOWN
     );
   }
 }
@@ -87,7 +87,7 @@ export class Nft extends BaseNft {
     tokenId: string,
     tokenType: NftTokenType,
     title: string,
-    description: string,
+    description: string | Array<string>,
     timeLastUpdated: string,
     tokenUri?: TokenUri,
     media?: TokenUri[],
@@ -96,7 +96,7 @@ export class Nft extends BaseNft {
   ) {
     super(address, tokenId, tokenType);
     this.title = title;
-    this.description = description;
+    this.description = Nft.parseDescription(description);
     this.timeLastUpdated = timeLastUpdated;
     this.metadataError = error;
     this.rawMetadata = metadata;
@@ -105,23 +105,30 @@ export class Nft extends BaseNft {
   }
 
   /** @internal */
-  static fromResponse(ownedNft: RawNft, contractAddress: string): Nft {
+  static fromResponse(nft: RawNft, contractAddress: string): Nft {
     return new Nft(
       contractAddress,
       // We have to normalize the token id here since the backend sometimes
       // returns the token ID as a hex string and sometimes as an integer string.
-      BigNumber.from(ownedNft.id.tokenId).toString(),
-      ownedNft.id.tokenMetadata?.tokenType ?? NftTokenType.UNKNOWN,
-      ownedNft.title,
-      ownedNft.description,
-      ownedNft.timeLastUpdated,
-      ownedNft.tokenUri,
-      ownedNft.media,
-      ownedNft.metadata,
-      ownedNft.error
+      BigNumber.from(nft.id.tokenId).toString(),
+      nft.id.tokenMetadata?.tokenType ?? NftTokenType.UNKNOWN,
+      nft.title,
+      nft.description,
+      nft.timeLastUpdated,
+      nft.tokenUri,
+      nft.media,
+      nft.metadata,
+      nft.error
     );
   }
 
+  /** @internal */
+  private static parseDescription(description: string | Array<string>): string {
+    return typeof description === 'string'
+      ? description
+      : description.join(' ');
+  }
+
   /**
    * Returns undefined if the uri has empty string fields.
    *
diff --git a/src/internal/raw-interfaces.ts b/src/internal/raw-interfaces.ts
index f8f496ee..bc61b930 100644
--- a/src/internal/raw-interfaces.ts
+++ b/src/internal/raw-interfaces.ts
@@ -22,7 +22,7 @@ export interface RawBaseNft {
  */
 export interface RawNft extends RawBaseNft {
   title: string;
-  description: string;
+  description: string | Array<string>;
   tokenUri?: TokenUri;
   media?: TokenUri[];
   metadata?: NftMetadata;


Test patch:
diff --git a/test/test-util.ts b/test/test-util.ts
index b80ad816..8f49ae85 100644
--- a/test/test-util.ts
+++ b/test/test-util.ts
@@ -88,11 +88,12 @@ export function createRawNft(
   tokenType = NftTokenType.UNKNOWN,
   tokenUri?: TokenUri,
   media?: TokenUri[] | undefined,
-  timeLastUpdated?: string
+  timeLastUpdated?: string,
+  description?: string | Array<string>
 ): RawNft {
   return {
     title,
-    description: `a truly unique NFT: ${title}`,
+    description: description ?? `a truly unique NFT: ${title}`,
     timeLastUpdated: timeLastUpdated ?? '2022-02-16T17:12:00.280Z',
     id: {
       tokenId,
diff --git a/test/unit/nft.test.ts b/test/unit/nft.test.ts
index c955bd2d..fc94b805 100644
--- a/test/unit/nft.test.ts
+++ b/test/unit/nft.test.ts
@@ -88,6 +88,22 @@ describe('Nft class', () => {
     expect(nft.media[2]).toEqual(rawMedia[3]);
   });
 
+  it('constructor merges descriptions when it is an array', () => {
+    const description = ['very', 'special', 'and unique', 'description'];
+
+    const rawNft = createRawNft(
+      'title',
+      tokenIdString,
+      NftTokenType.ERC721,
+      { raw: '', gateway: '' },
+      [],
+      '2022-02-16T17:12:00.280Z',
+      description
+    );
+    const nft = Nft.fromResponse(rawNft, '0xCA1');
+    expect(nft.description).toEqual('very special and unique description');
+  });
+
   it('media field is set to empty array even if undefined ', () => {
     const nft = createNft(
       'title',