@@ -2,18 +2,23 @@ import type { OpenSeaClientConfig } from "./types/index.js"
22
33const DEFAULT_BASE_URL = "https://api.opensea.io"
44const DEFAULT_GRAPHQL_URL = "https://gql.opensea.io/graphql"
5+ const DEFAULT_TIMEOUT_MS = 30_000
56
67export class OpenSeaClient {
78 private apiKey : string
89 private baseUrl : string
910 private graphqlUrl : string
1011 private defaultChain : string
12+ private timeoutMs : number
13+ private verbose : boolean
1114
1215 constructor ( config : OpenSeaClientConfig ) {
1316 this . apiKey = config . apiKey
1417 this . baseUrl = config . baseUrl ?? DEFAULT_BASE_URL
1518 this . graphqlUrl = config . graphqlUrl ?? DEFAULT_GRAPHQL_URL
1619 this . defaultChain = config . chain ?? "ethereum"
20+ this . timeoutMs = config . timeout ?? DEFAULT_TIMEOUT_MS
21+ this . verbose = config . verbose ?? false
1722 }
1823
1924 async get < T > ( path : string , params ?: Record < string , unknown > ) : Promise < T > {
@@ -27,14 +32,23 @@ export class OpenSeaClient {
2732 }
2833 }
2934
35+ if ( this . verbose ) {
36+ console . error ( `[verbose] GET ${ url . toString ( ) } ` )
37+ }
38+
3039 const response = await fetch ( url . toString ( ) , {
3140 method : "GET" ,
3241 headers : {
3342 Accept : "application/json" ,
3443 "x-api-key" : this . apiKey ,
3544 } ,
45+ signal : AbortSignal . timeout ( this . timeoutMs ) ,
3646 } )
3747
48+ if ( this . verbose ) {
49+ console . error ( `[verbose] ${ response . status } ${ response . statusText } ` )
50+ }
51+
3852 if ( ! response . ok ) {
3953 const body = await response . text ( )
4054 throw new OpenSeaAPIError ( response . status , body , path )
@@ -43,20 +57,48 @@ export class OpenSeaClient {
4357 return response . json ( ) as Promise < T >
4458 }
4559
46- async post < T > ( path : string ) : Promise < T > {
60+ async post < T > (
61+ path : string ,
62+ body ?: Record < string , unknown > ,
63+ params ?: Record < string , unknown > ,
64+ ) : Promise < T > {
4765 const url = new URL ( `${ this . baseUrl } ${ path } ` )
4866
67+ if ( params ) {
68+ for ( const [ key , value ] of Object . entries ( params ) ) {
69+ if ( value !== undefined && value !== null ) {
70+ url . searchParams . set ( key , String ( value ) )
71+ }
72+ }
73+ }
74+
75+ const headers : Record < string , string > = {
76+ Accept : "application/json" ,
77+ "x-api-key" : this . apiKey ,
78+ }
79+
80+ if ( body ) {
81+ headers [ "Content-Type" ] = "application/json"
82+ }
83+
84+ if ( this . verbose ) {
85+ console . error ( `[verbose] POST ${ url . toString ( ) } ` )
86+ }
87+
4988 const response = await fetch ( url . toString ( ) , {
5089 method : "POST" ,
51- headers : {
52- Accept : "application/json" ,
53- "x-api-key" : this . apiKey ,
54- } ,
90+ headers,
91+ body : body ? JSON . stringify ( body ) : undefined ,
92+ signal : AbortSignal . timeout ( this . timeoutMs ) ,
5593 } )
5694
95+ if ( this . verbose ) {
96+ console . error ( `[verbose] ${ response . status } ${ response . statusText } ` )
97+ }
98+
5799 if ( ! response . ok ) {
58- const body = await response . text ( )
59- throw new OpenSeaAPIError ( response . status , body , path )
100+ const text = await response . text ( )
101+ throw new OpenSeaAPIError ( response . status , text , path )
60102 }
61103
62104 return response . json ( ) as Promise < T >
@@ -66,6 +108,10 @@ export class OpenSeaClient {
66108 query : string ,
67109 variables ?: Record < string , unknown > ,
68110 ) : Promise < T > {
111+ if ( this . verbose ) {
112+ console . error ( `[verbose] POST ${ this . graphqlUrl } ` )
113+ }
114+
69115 const response = await fetch ( this . graphqlUrl , {
70116 method : "POST" ,
71117 headers : {
@@ -74,8 +120,13 @@ export class OpenSeaClient {
74120 "x-api-key" : this . apiKey ,
75121 } ,
76122 body : JSON . stringify ( { query, variables } ) ,
123+ signal : AbortSignal . timeout ( this . timeoutMs ) ,
77124 } )
78125
126+ if ( this . verbose ) {
127+ console . error ( `[verbose] ${ response . status } ${ response . statusText } ` )
128+ }
129+
79130 if ( ! response . ok ) {
80131 const body = await response . text ( )
81132 throw new OpenSeaAPIError ( response . status , body , "graphql" )
0 commit comments