diff --git a/cspell.json b/cspell.json index a8d935375..392450dfc 100644 --- a/cspell.json +++ b/cspell.json @@ -58,6 +58,7 @@ "Merkle", "microether", "milliether", + "offchain", "pako", "payloadset", "Promisable", diff --git a/packages/payloadset/packages/api/src/Payload.ts b/packages/payloadset/packages/api/src/Payload.ts index 95c63d2bf..3b0ca2354 100644 --- a/packages/payloadset/packages/api/src/Payload.ts +++ b/packages/payloadset/packages/api/src/Payload.ts @@ -1,5 +1,5 @@ import { Hash } from '@xylabs/hex' -import { AsObjectFactory } from '@xyo-network/object' +import { AsObjectFactory, JsonArray, JsonObject } from '@xyo-network/object' import { isPayloadOfSchemaType, Payload } from '@xyo-network/payload-model' export const ApiCallSchema = 'network.xyo.api.call' @@ -38,7 +38,9 @@ export interface HttpMeta { status?: number } -export type ApiCallJsonResult = Payload< +export type ApiCallJsonResultType = JsonArray | JsonObject + +export type ApiCallJsonResult = Payload< { call: Hash contentType: 'application/json' @@ -64,7 +66,10 @@ export type ApiCallErrorResult = Payload< ApiCallResultSchema > -export type ApiCallResult = ApiCallBase64Result | ApiCallJsonResult | ApiCallErrorResult +export type ApiCallResult = + | ApiCallBase64Result + | ApiCallJsonResult + | ApiCallErrorResult export const isApiCall = isPayloadOfSchemaType(ApiCallSchema) export const asApiCall = AsObjectFactory.create(isApiCall) diff --git a/packages/payloadset/packages/api/src/Witness.ts b/packages/payloadset/packages/api/src/Witness.ts index a7a88f003..dc5883ef4 100644 --- a/packages/payloadset/packages/api/src/Witness.ts +++ b/packages/payloadset/packages/api/src/Witness.ts @@ -3,7 +3,6 @@ import { Axios, AxiosError, AxiosJson } from '@xylabs/axios' import { Hash } from '@xylabs/hex' import { AbstractWitness } from '@xyo-network/abstract-witness' import { PayloadHasher } from '@xyo-network/hash' -import { JsonArray, JsonObject } from '@xyo-network/object' import { isPayloadOfSchemaType } from '@xyo-network/payload-model' import { WitnessParams } from '@xyo-network/witness-model' import { fromByteArray } from 'base64-js' @@ -16,6 +15,7 @@ import { ApiCallBase64Result, ApiCallErrorResult, ApiCallJsonResult, + ApiCallJsonResultType, ApiCallResult, ApiCallResultSchema, ApiCallSchema, @@ -116,7 +116,7 @@ export class ApiCallWitness(url) + const response = await axios.get(url) if (response.status >= 200 && response.status < 300) { const jsonResult = result as ApiCallJsonResult jsonResult.data = response.data diff --git a/packages/payloadset/packages/api/src/spec/opensea.nft-call.spec.ts b/packages/payloadset/packages/api/src/spec/opensea.nft-call.spec.ts index b5d0ad09b..bb01a4f6e 100644 --- a/packages/payloadset/packages/api/src/spec/opensea.nft-call.spec.ts +++ b/packages/payloadset/packages/api/src/spec/opensea.nft-call.spec.ts @@ -1,5 +1,4 @@ /* eslint-disable max-statements */ - import { describeIf } from '@xylabs/jest-helpers' import { HDWallet } from '@xyo-network/account' import { ManifestWrapper, PackageManifestPayload } from '@xyo-network/manifest' @@ -8,7 +7,7 @@ import { isPayloadOfSchemaType } from '@xyo-network/payload-model' import { asSentinelInstance } from '@xyo-network/sentinel-model' import { asWitnessInstance } from '@xyo-network/witness-model' -import { ApiCallJsonResult, ApiCallResult, ApiCallResultSchema, ApiCallSchema, ApiUriTemplateCall } from '../Payload' +import { ApiCallJsonResult, ApiCallResultSchema, ApiCallSchema, ApiUriTemplateCall } from '../Payload' import { ApiCallWitness } from '../Witness' import openseaNftsManifest from './opensea.nft-call.json' @@ -18,6 +17,60 @@ describe('OpenSeaApi', () => { const apiKey = process.env.OPENSEA_API_KEY describeIf(apiKey)('report', () => { + type OpenSeaNft = { + /* + * Collection slug. A unique string to identify a collection on OpenSea + */ + collection: string + /* + * The unique public blockchain identifier for the contract + */ + contract: string + /** + * @deprecated + */ + created_at: string + /* + * Description of the NFT + */ + description: string + /* + * The NFT's unique identifier within the smart contract (also referred to as token_id) + */ + identifier: string + /* + * Link to the image associated with the NFT + */ + image_url: string + /* + * If the item is currently able to be bought or sold using OpenSea + */ + is_disabled: boolean + /* + * If the item is currently classified as 'Not Safe for Work' by OpenSea as defined in OpenSea's NSFW Policy. + */ + is_nsfw: boolean + /* + * Link to the offchain metadata store + */ + metadata_url: string + /* + * Name of the NFT + */ + name: string + /* + * ERC standard of the token (erc721, erc1155) + */ + token_standard: string + /* + * Last time that the NFT's metadata was updated by OpenSea + */ + updated_at: string + } + type OpenSeaListNftsByAccountResponse = { + next: string + nfts: OpenSeaNft[] + } it('specifying address', async () => { const mnemonic = 'later puppy sound rebuild rebuild noise ozone amazing hope broccoli crystal grief' const wallet = await HDWallet.fromPhrase(mnemonic) @@ -51,11 +104,11 @@ describe('OpenSeaApi', () => { const report = await sentinel?.report([call]) - const apiCallResult = report?.find(isPayloadOfSchemaType(ApiCallResultSchema)) as ApiCallResult | undefined - + const apiCallResult = report?.find(isPayloadOfSchemaType>(ApiCallResultSchema)) + expect(apiCallResult).toBeDefined() expect(apiCallResult?.schema).toBeString() - // eslint-disable-next-line @typescript-eslint/no-explicit-any - expect((apiCallResult as ApiCallJsonResult)?.data.nfts).toBeArrayOfSize(1) + expect(apiCallResult?.data.nfts).toBeArrayOfSize(1) + expect(apiCallResult?.data.nfts[0].collection).toBeString() }) }) })