@0xobelisk/sui-client 1.0.7 → 1.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- import { WebSocket } from 'ws';
1
+ import { WebSocketInstance } from './ws-adapter';
2
2
  export type FetchOptions = RequestInit & {
3
3
  next?: {
4
4
  revalidate?: boolean | number;
@@ -17,5 +17,5 @@ export declare class Http {
17
17
  query: string;
18
18
  variables?: any;
19
19
  }): Promise<T>;
20
- subscribe(names: string[], handleData: (data: any) => void): Promise<WebSocket>;
20
+ subscribe(names: string[], handleData: (data: any) => void): Promise<WebSocketInstance>;
21
21
  }
@@ -0,0 +1,6 @@
1
+ export type WebSocketInstance = WebSocket;
2
+ export interface WebSocketConstructor {
3
+ new (url: string): WebSocket;
4
+ }
5
+ export declare function createWebSocketClient(url: string): WebSocketInstance;
6
+ export declare function isWebSocketSupported(): boolean;
@@ -1,25 +1,19 @@
1
1
  import { Http } from '../http';
2
- import { WebSocket } from 'ws';
3
2
  export interface OrderDirection {
4
3
  ASC: 'ASC';
5
4
  DESC: 'DESC';
6
5
  }
7
- export interface OrderBy {
8
- field: string;
9
- direction: OrderDirection['ASC'] | OrderDirection['DESC'];
10
- }
11
6
  export interface PageInfo {
12
7
  hasNextPage: boolean;
13
- hasPreviousPage: boolean;
14
- startCursor?: string;
15
8
  endCursor?: string;
16
9
  }
17
- export interface Transaction {
10
+ export interface IndexerTransaction {
18
11
  id: number;
19
12
  checkpoint: number;
20
13
  digest: string;
14
+ created_at: string;
21
15
  }
22
- export interface Schema {
16
+ export interface IndexerSchema {
23
17
  id: number;
24
18
  name: string;
25
19
  key1?: string;
@@ -28,13 +22,16 @@ export interface Schema {
28
22
  last_update_checkpoint: string;
29
23
  last_update_digest: string;
30
24
  is_removed: boolean;
25
+ created_at: string;
26
+ updated_at: string;
31
27
  }
32
- export interface Event {
28
+ export interface IndexerEvent {
33
29
  id: number;
34
30
  checkpoint: string;
35
31
  digest: string;
36
32
  name: string;
37
33
  value: string;
34
+ created_at: string;
38
35
  }
39
36
  export interface ConnectionResponse<T> {
40
37
  edges: Array<{
@@ -42,6 +39,17 @@ export interface ConnectionResponse<T> {
42
39
  node: T;
43
40
  }>;
44
41
  pageInfo: PageInfo;
42
+ totalCount: number;
43
+ }
44
+ export interface StorageResponse<T> {
45
+ data: T[];
46
+ value: any[];
47
+ pageInfo: PageInfo;
48
+ totalCount: number;
49
+ }
50
+ export interface StorageItemResponse<T> {
51
+ data: T;
52
+ value: any;
45
53
  }
46
54
  export declare class SuiIndexerClient {
47
55
  private http;
@@ -50,43 +58,36 @@ export declare class SuiIndexerClient {
50
58
  getTransactions(params?: {
51
59
  first?: number;
52
60
  after?: string;
53
- last?: number;
54
- before?: string;
55
61
  checkpoint?: number;
56
- orderBy?: OrderBy;
57
- distinct?: boolean;
58
- }): Promise<ConnectionResponse<Transaction>>;
62
+ orderBy?: string[];
63
+ }): Promise<ConnectionResponse<IndexerTransaction>>;
59
64
  getSchemas(params?: {
60
65
  first?: number;
61
66
  after?: string;
62
- last?: number;
63
- before?: string;
64
67
  name?: string;
65
68
  key1?: string;
66
69
  key2?: string;
67
- orderBy?: OrderBy;
68
- distinct?: boolean;
69
- }): Promise<ConnectionResponse<Schema>>;
70
+ orderBy?: string[];
71
+ }): Promise<ConnectionResponse<IndexerSchema>>;
70
72
  getEvents(params?: {
71
73
  first?: number;
72
74
  after?: string;
73
- last?: number;
74
- before?: string;
75
75
  name?: string;
76
76
  checkpoint?: string;
77
- orderBy?: OrderBy;
78
- distinct?: boolean;
79
- }): Promise<ConnectionResponse<Event>>;
80
- getStorage({ name, key1, key2, first, after, last, before, orderBy, distinct, }: {
81
- name: string;
77
+ orderBy?: string[];
78
+ }): Promise<ConnectionResponse<IndexerEvent>>;
79
+ getStorage({ name, key1, key2, first, after, orderBy, }: {
80
+ name?: string;
82
81
  key1?: string;
83
82
  key2?: string;
84
83
  first?: number;
85
84
  after?: string;
86
- last?: number;
87
- before?: string;
88
- orderBy?: OrderBy;
89
- distinct?: boolean;
90
- }): Promise<ConnectionResponse<Schema>>;
85
+ orderBy?: string[];
86
+ }): Promise<StorageResponse<IndexerSchema>>;
87
+ getStorageItem({ name, key1, key2, }: {
88
+ name: string;
89
+ key1?: string;
90
+ key2?: string;
91
+ }): Promise<StorageItemResponse<IndexerSchema> | undefined>;
91
92
  subscribe(names: string[], handleData: (data: any) => void): Promise<WebSocket>;
92
93
  }
@@ -0,0 +1 @@
1
+ export declare const parseValue: (value: unknown) => unknown;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@0xobelisk/sui-client",
3
- "version": "1.0.7",
3
+ "version": "1.0.9",
4
4
  "description": "Tookit for interacting with move eps framework",
5
5
  "keywords": [
6
6
  "sui",
@@ -57,7 +57,8 @@
57
57
  "tmp": "^0.2.1",
58
58
  "ts-retry-promise": "^0.7.1",
59
59
  "tweetnacl": "^1.0.3",
60
- "valibot": "0.36.0"
60
+ "valibot": "0.36.0",
61
+ "ws": "^8.18.0"
61
62
  },
62
63
  "devDependencies": {
63
64
  "@commitlint/cli": "^18.0.0",
@@ -66,7 +67,6 @@
66
67
  "@types/jest": "^29.5.14",
67
68
  "@types/node": "^20.8.7",
68
69
  "@types/tmp": "^0.2.5",
69
- "@types/ws": "^8.5.14",
70
70
  "@typescript-eslint/eslint-plugin": "^6.8.0",
71
71
  "@typescript-eslint/parser": "^6.8.0",
72
72
  "dotenv": "^16.3.1",
@@ -82,7 +82,7 @@
82
82
  "tsup": "^7.1.0",
83
83
  "typedoc": "^0.25.2",
84
84
  "typescript": "^5.2.2",
85
- "ws": "^8.18.0"
85
+ "@types/ws": "^8.5.14"
86
86
  },
87
87
  "lint-staged": {
88
88
  "**/*.ts": [
package/src/dubhe.ts CHANGED
@@ -50,12 +50,14 @@ import { bcs, fromHEX, toHEX } from '@mysten/bcs';
50
50
  import { ContractDataParsingError } from './errors';
51
51
  import {
52
52
  ConnectionResponse,
53
- OrderBy,
54
- Schema,
53
+ IndexerTransaction,
54
+ IndexerEvent,
55
+ IndexerSchema,
55
56
  SuiIndexerClient,
57
+ StorageResponse,
58
+ StorageItemResponse,
56
59
  } from './libs/suiIndexerClient';
57
60
  import { Http } from './libs/http';
58
- import { WebSocket } from 'ws';
59
61
 
60
62
  export function isUndefined(value?: unknown): value is undefined {
61
63
  return value === undefined;
@@ -1110,40 +1112,101 @@ export class Dubhe {
1110
1112
  });
1111
1113
  }
1112
1114
 
1115
+ async getTransactions({
1116
+ first,
1117
+ after,
1118
+ orderBy,
1119
+ }: {
1120
+ first?: number;
1121
+ after?: string;
1122
+ orderBy?: string[];
1123
+ }): Promise<ConnectionResponse<IndexerTransaction>> {
1124
+ return await this.suiIndexerClient.getTransactions({
1125
+ first,
1126
+ after,
1127
+ orderBy,
1128
+ });
1129
+ }
1130
+
1131
+ async getEvents({
1132
+ first,
1133
+ after,
1134
+ orderBy,
1135
+ }: {
1136
+ first?: number;
1137
+ after?: string;
1138
+ orderBy?: string[];
1139
+ }): Promise<ConnectionResponse<IndexerEvent>> {
1140
+ return await this.suiIndexerClient.getEvents({ first, after, orderBy });
1141
+ }
1142
+
1143
+ async getSchemas({
1144
+ name,
1145
+ key1,
1146
+ key2,
1147
+ first,
1148
+ after,
1149
+ orderBy,
1150
+ }: {
1151
+ name?: string;
1152
+ key1?: string;
1153
+ key2?: string;
1154
+ first?: number;
1155
+ after?: string;
1156
+ orderBy?: string[];
1157
+ }): Promise<ConnectionResponse<IndexerSchema>> {
1158
+ return await this.suiIndexerClient.getSchemas({
1159
+ name,
1160
+ key1,
1161
+ key2,
1162
+ first,
1163
+ after,
1164
+ orderBy,
1165
+ });
1166
+ }
1167
+
1113
1168
  async getStorage({
1114
1169
  name,
1115
1170
  key1,
1116
1171
  key2,
1117
1172
  first,
1118
1173
  after,
1119
- last,
1120
- before,
1121
1174
  orderBy,
1122
- distinct,
1123
1175
  }: {
1124
- name: string;
1176
+ name?: string;
1125
1177
  key1?: string;
1126
1178
  key2?: string;
1127
1179
  first?: number;
1128
1180
  after?: string;
1129
- last?: number;
1130
- before?: string;
1131
- orderBy?: OrderBy;
1132
- distinct?: boolean;
1133
- }): Promise<ConnectionResponse<Schema>> {
1181
+ orderBy?: string[];
1182
+ }): Promise<StorageResponse<IndexerSchema>> {
1134
1183
  return await this.suiIndexerClient.getStorage({
1135
1184
  name,
1136
1185
  key1,
1137
1186
  key2,
1138
1187
  first,
1139
1188
  after,
1140
- last,
1141
- before,
1142
1189
  orderBy,
1143
- distinct,
1144
1190
  });
1145
1191
  }
1146
1192
 
1193
+ async getStorageItem({
1194
+ name,
1195
+ key1,
1196
+ key2,
1197
+ }: {
1198
+ name: string;
1199
+ key1?: string;
1200
+ key2?: string;
1201
+ }): Promise<StorageItemResponse<IndexerSchema> | undefined> {
1202
+ const response = await this.suiIndexerClient.getStorageItem({
1203
+ name,
1204
+ key1,
1205
+ key2,
1206
+ });
1207
+ return response;
1208
+ }
1209
+
1147
1210
  async subscribe(
1148
1211
  names: string[],
1149
1212
  handleData: (data: any) => void
@@ -1,5 +1,5 @@
1
- import { WebSocket } from 'ws';
2
1
  import { BaseError, HttpError, GraphQLError, ParseError } from './errors';
2
+ import { createWebSocketClient, WebSocketInstance } from './ws-adapter';
3
3
 
4
4
  export type FetchOptions = RequestInit & {
5
5
  next?: {
@@ -62,7 +62,6 @@ export class Http {
62
62
  try {
63
63
  const isFirstPage = variables?.after === 'first';
64
64
  const fetchFn = this.getFetch();
65
- console.log(query);
66
65
  const response = await fetchFn(this.graphqlEndpoint, {
67
66
  method: 'POST',
68
67
  headers: {
@@ -109,7 +108,6 @@ export class Http {
109
108
 
110
109
  return data.data;
111
110
  } catch (error) {
112
- console.log(error);
113
111
  if (error instanceof BaseError) {
114
112
  throw error;
115
113
  }
@@ -123,30 +121,32 @@ export class Http {
123
121
  }
124
122
  }
125
123
 
126
- async subscribe(names: string[], handleData: (data: any) => void): Promise<WebSocket> {
127
- const ws = new WebSocket(this.wsEndpoint);
124
+ async subscribe(
125
+ names: string[],
126
+ handleData: (data: any) => void
127
+ ): Promise<WebSocketInstance> {
128
+ const ws = createWebSocketClient(this.wsEndpoint);
128
129
 
129
- ws.on('open', () => {
130
+ ws.onopen = () => {
130
131
  console.log('Connected to the WebSocket server');
131
- // Subscribe to specific event names
132
132
  const subscribeMessage = JSON.stringify({
133
133
  type: 'subscribe',
134
134
  names: names,
135
135
  });
136
136
  ws.send(subscribeMessage);
137
- });
137
+ };
138
138
 
139
- ws.on('message', (data) => {
140
- handleData(JSON.parse(data.toString()));
141
- });
139
+ ws.onmessage = (event) => {
140
+ handleData(JSON.parse(event.data.toString()));
141
+ };
142
142
 
143
- ws.on('close', () => {
143
+ ws.onclose = () => {
144
144
  console.log('Disconnected from the WebSocket server');
145
- });
145
+ };
146
146
 
147
- ws.on('error', (error) => {
148
- console.error(`WebSocket error: ${error}`);
149
- });
147
+ ws.onerror = (error) => {
148
+ console.error(`WebSocket error:`, error);
149
+ };
150
150
 
151
151
  return ws;
152
152
  }
@@ -0,0 +1,36 @@
1
+ export type WebSocketInstance = WebSocket;
2
+
3
+ export interface WebSocketConstructor {
4
+ new (url: string): WebSocket;
5
+ }
6
+
7
+ export function createWebSocketClient(url: string): WebSocketInstance {
8
+ if (typeof window !== 'undefined') {
9
+ // Browser Environment
10
+ return new WebSocket(url);
11
+ } else {
12
+ // Node.js Environment
13
+ try {
14
+ require.resolve('ws');
15
+ const WebSocket = require('ws');
16
+ return new WebSocket(url);
17
+ } catch (e) {
18
+ console.error('Failed to load WebSocket implementation:', e);
19
+ throw new Error(
20
+ 'WebSocket implementation not available. Please install the "ws" package.'
21
+ );
22
+ }
23
+ }
24
+ }
25
+
26
+ export function isWebSocketSupported(): boolean {
27
+ if (typeof window !== 'undefined') {
28
+ return typeof WebSocket !== 'undefined';
29
+ }
30
+ try {
31
+ require.resolve('ws');
32
+ return true;
33
+ } catch {
34
+ return false;
35
+ }
36
+ }
@@ -1,30 +1,29 @@
1
1
  import { Http } from '../http';
2
- import { WebSocket } from 'ws';
2
+ import { parseValue } from './utils';
3
3
 
4
4
  export interface OrderDirection {
5
5
  ASC: 'ASC';
6
6
  DESC: 'DESC';
7
7
  }
8
8
 
9
- export interface OrderBy {
10
- field: string;
11
- direction: OrderDirection['ASC'] | OrderDirection['DESC'];
12
- }
9
+ // export interface OrderBy {
10
+ // field: string;
11
+ // direction: OrderDirection['ASC'] | OrderDirection['DESC'];
12
+ // }
13
13
 
14
14
  export interface PageInfo {
15
15
  hasNextPage: boolean;
16
- hasPreviousPage: boolean;
17
- startCursor?: string;
18
16
  endCursor?: string;
19
17
  }
20
18
 
21
- export interface Transaction {
19
+ export interface IndexerTransaction {
22
20
  id: number;
23
21
  checkpoint: number;
24
22
  digest: string;
23
+ created_at: string;
25
24
  }
26
25
 
27
- export interface Schema {
26
+ export interface IndexerSchema {
28
27
  id: number;
29
28
  name: string;
30
29
  key1?: string;
@@ -33,14 +32,17 @@ export interface Schema {
33
32
  last_update_checkpoint: string;
34
33
  last_update_digest: string;
35
34
  is_removed: boolean;
35
+ created_at: string;
36
+ updated_at: string;
36
37
  }
37
38
 
38
- export interface Event {
39
+ export interface IndexerEvent {
39
40
  id: number;
40
41
  checkpoint: string;
41
42
  digest: string;
42
43
  name: string;
43
44
  value: string;
45
+ created_at: string;
44
46
  }
45
47
 
46
48
  export interface ConnectionResponse<T> {
@@ -49,6 +51,19 @@ export interface ConnectionResponse<T> {
49
51
  node: T;
50
52
  }>;
51
53
  pageInfo: PageInfo;
54
+ totalCount: number;
55
+ }
56
+
57
+ export interface StorageResponse<T> {
58
+ data: T[];
59
+ value: any[];
60
+ pageInfo: PageInfo;
61
+ totalCount: number;
62
+ }
63
+
64
+ export interface StorageItemResponse<T> {
65
+ data: T;
66
+ value: any;
52
67
  }
53
68
 
54
69
  export class SuiIndexerClient {
@@ -65,35 +80,32 @@ export class SuiIndexerClient {
65
80
  async getTransactions(params?: {
66
81
  first?: number;
67
82
  after?: string;
68
- last?: number;
69
- before?: string;
70
83
  checkpoint?: number;
71
- orderBy?: OrderBy;
72
- distinct?: boolean;
84
+ orderBy?: string[];
73
85
  }) {
74
86
  const query = `
75
- query GetTransactions($first: Int, $after: String, $last: Int, $before: String, $checkpoint: Int, $orderBy: TransactionOrderBy, $distinct: Boolean) {
76
- transactions(first: $first, after: $after, last: $last, before: $before, checkpoint: $checkpoint, orderBy: $orderBy, distinct: $distinct) {
87
+ query GetTransactions($first: Int, $after: String, $checkpoint: Int, $orderBy: [TransactionOrderField!]) {
88
+ transactions(first: $first, after: $after, checkpoint: $checkpoint, orderBy: $orderBy) {
77
89
  edges {
78
90
  cursor
79
91
  node {
80
92
  id
81
93
  checkpoint
82
94
  digest
95
+ created_at
83
96
  }
84
97
  }
85
98
  pageInfo {
86
99
  hasNextPage
87
- hasPreviousPage
88
- startCursor
89
100
  endCursor
90
101
  }
102
+ totalCount
91
103
  }
92
104
  }
93
105
  `;
94
106
 
95
107
  const response = await this.fetchGraphql<{
96
- transactions: ConnectionResponse<Transaction>;
108
+ transactions: ConnectionResponse<IndexerTransaction>;
97
109
  }>(query, params);
98
110
  return response.transactions;
99
111
  }
@@ -101,17 +113,14 @@ export class SuiIndexerClient {
101
113
  async getSchemas(params?: {
102
114
  first?: number;
103
115
  after?: string;
104
- last?: number;
105
- before?: string;
106
116
  name?: string;
107
117
  key1?: string;
108
118
  key2?: string;
109
- orderBy?: OrderBy;
110
- distinct?: boolean;
111
- }): Promise<ConnectionResponse<Schema>> {
119
+ orderBy?: string[];
120
+ }): Promise<ConnectionResponse<IndexerSchema>> {
112
121
  const query = `
113
- query GetSchemas($first: Int, $after: String, $last: Int, $before: String, $name: String, $key1: String, $key2: String, $orderBy: SchemaOrderBy, $distinct: Boolean) {
114
- schemas(first: $first, after: $after, last: $last, before: $before, name: $name, key1: $key1, key2: $key2, orderBy: $orderBy, distinct: $distinct) {
122
+ query GetSchemas($first: Int, $after: String, $name: String, $key1: String, $key2: String, $orderBy: [SchemaOrderField!]) {
123
+ schemas(first: $first, after: $after, name: $name, key1: $key1, key2: $key2, orderBy: $orderBy) {
115
124
  edges {
116
125
  cursor
117
126
  node {
@@ -123,20 +132,21 @@ export class SuiIndexerClient {
123
132
  last_update_checkpoint
124
133
  last_update_digest
125
134
  is_removed
135
+ created_at
136
+ updated_at
126
137
  }
127
138
  }
128
139
  pageInfo {
129
140
  hasNextPage
130
- hasPreviousPage
131
- startCursor
132
141
  endCursor
133
142
  }
143
+ totalCount
134
144
  }
135
145
  }
136
146
  `;
137
147
 
138
148
  const response = await this.fetchGraphql<{
139
- schemas: ConnectionResponse<Schema>;
149
+ schemas: ConnectionResponse<IndexerSchema>;
140
150
  }>(query, params);
141
151
  return response.schemas;
142
152
  }
@@ -144,16 +154,13 @@ export class SuiIndexerClient {
144
154
  async getEvents(params?: {
145
155
  first?: number;
146
156
  after?: string;
147
- last?: number;
148
- before?: string;
149
157
  name?: string;
150
158
  checkpoint?: string;
151
- orderBy?: OrderBy;
152
- distinct?: boolean;
153
- }) {
159
+ orderBy?: string[];
160
+ }): Promise<ConnectionResponse<IndexerEvent>> {
154
161
  const query = `
155
- query GetEvents($first: Int, $after: String, $last: Int, $before: String, $name: String, $checkpoint: String, $orderBy: EventOrderBy, $distinct: Boolean) {
156
- events(first: $first, after: $after, last: $last, before: $before, name: $name, checkpoint: $checkpoint, orderBy: $orderBy, distinct: $distinct) {
162
+ query GetEvents($first: Int, $after: String, $name: String, $checkpoint: String, $orderBy: [EventOrderField!]) {
163
+ events(first: $first, after: $after, name: $name, checkpoint: $checkpoint, orderBy: $orderBy) {
157
164
  edges {
158
165
  cursor
159
166
  node {
@@ -162,20 +169,20 @@ export class SuiIndexerClient {
162
169
  digest
163
170
  name
164
171
  value
172
+ created_at
165
173
  }
166
174
  }
167
175
  pageInfo {
168
176
  hasNextPage
169
- hasPreviousPage
170
- startCursor
171
177
  endCursor
172
178
  }
179
+ totalCount
173
180
  }
174
181
  }
175
182
  `;
176
183
 
177
184
  const response = await this.fetchGraphql<{
178
- events: ConnectionResponse<Event>;
185
+ events: ConnectionResponse<IndexerEvent>;
179
186
  }>(query, params);
180
187
  return response.events;
181
188
  }
@@ -186,34 +193,57 @@ export class SuiIndexerClient {
186
193
  key2,
187
194
  first,
188
195
  after,
189
- last,
190
- before,
191
196
  orderBy,
192
- distinct,
193
197
  }: {
194
- name: string;
198
+ name?: string;
195
199
  key1?: string;
196
200
  key2?: string;
197
201
  first?: number;
198
202
  after?: string;
199
- last?: number;
200
- before?: string;
201
- orderBy?: OrderBy;
202
- distinct?: boolean;
203
- }): Promise<ConnectionResponse<Schema>> {
203
+ orderBy?: string[];
204
+ }): Promise<StorageResponse<IndexerSchema>> {
204
205
  const schemas = await this.getSchemas({
205
206
  name,
206
207
  key1,
207
208
  key2,
208
209
  first,
209
210
  after,
210
- last,
211
- before,
212
211
  orderBy,
213
- distinct,
214
212
  });
213
+ const data = schemas.edges.map((edge) => edge.node);
214
+ const value = data.map((item) => parseValue(item.value));
215
+ return {
216
+ data,
217
+ value,
218
+ pageInfo: schemas.pageInfo,
219
+ totalCount: schemas.totalCount,
220
+ };
221
+ }
215
222
 
216
- return schemas;
223
+ async getStorageItem({
224
+ name,
225
+ key1,
226
+ key2,
227
+ }: {
228
+ name: string;
229
+ key1?: string;
230
+ key2?: string;
231
+ }): Promise<StorageItemResponse<IndexerSchema> | undefined> {
232
+ const schemas = await this.getSchemas({
233
+ name,
234
+ key1,
235
+ key2,
236
+ first: 1,
237
+ });
238
+ const data = schemas.edges[0]?.node;
239
+ if (!data) {
240
+ return undefined;
241
+ }
242
+ const value = parseValue(data.value);
243
+ return {
244
+ data,
245
+ value,
246
+ };
217
247
  }
218
248
 
219
249
  async subscribe(