@exodus/sui-api 1.0.0 → 1.0.2

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,178 +0,0 @@
1
- import { JsonRpcError } from './errors.js'
2
-
3
- function getWebsocketUrl(httpUrl) {
4
- const url = new URL(httpUrl)
5
- url.protocol = url.protocol.replace('http', 'ws')
6
- return url.toString()
7
- }
8
-
9
- export const DEFAULT_CLIENT_OPTIONS = {
10
- // We fudge the typing because we also check for undefined in the constructor:
11
- // eslint-disable-next-line no-undef
12
- WebSocketConstructor: typeof WebSocket === 'undefined' ? undefined : WebSocket, // eslint-disable-line @typescript-eslint/no-unsafe-assignment
13
- callTimeout: 30_000,
14
- reconnectTimeout: 3000,
15
- maxReconnects: 5,
16
- }
17
-
18
- export class WebsocketClient {
19
- endpoint
20
- options
21
- #requestId = 0
22
- #disconnects = 0
23
- #webSocket = null
24
- #connectionPromise = null
25
- #subscriptions = new Set()
26
- #pendingRequests = new Map()
27
-
28
- constructor(endpoint, options = Object.create(null)) {
29
- this.endpoint = endpoint
30
- this.options = { ...DEFAULT_CLIENT_OPTIONS, ...options }
31
-
32
- if (!this.options.WebSocketConstructor) {
33
- throw new Error('Missing WebSocket constructor')
34
- }
35
-
36
- if (this.endpoint.startsWith('http')) {
37
- this.endpoint = getWebsocketUrl(this.endpoint)
38
- }
39
- }
40
-
41
- async makeRequest(method, params, signal) {
42
- const webSocket = await this.#setupWebSocket()
43
-
44
- return new Promise((resolve, reject) => {
45
- this.#requestId += 1
46
- this.#pendingRequests.set(this.#requestId, {
47
- resolve,
48
- reject,
49
- timeout: setTimeout(() => {
50
- this.#pendingRequests.delete(this.#requestId)
51
- reject(new Error(`Request timeout: ${method}`))
52
- }, this.options.callTimeout),
53
- })
54
-
55
- signal?.addEventListener('abort', () => {
56
- this.#pendingRequests.delete(this.#requestId)
57
- reject(signal.reason)
58
- })
59
-
60
- webSocket.send(JSON.stringify({ jsonrpc: '2.0', id: this.#requestId, method, params }))
61
- }).then(({ error, result }) => {
62
- if (error) {
63
- throw new JsonRpcError(error.message, error.code)
64
- }
65
-
66
- return result
67
- })
68
- }
69
-
70
- #setupWebSocket() {
71
- if (this.#connectionPromise) {
72
- return this.#connectionPromise
73
- }
74
-
75
- this.#connectionPromise = new Promise((resolve) => {
76
- this.#webSocket?.close()
77
- this.#webSocket = new this.options.WebSocketConstructor(this.endpoint)
78
-
79
- this.#webSocket.addEventListener('open', () => {
80
- this.#disconnects = 0
81
- resolve(this.#webSocket)
82
- })
83
-
84
- this.#webSocket.addEventListener('close', () => {
85
- this.#disconnects++
86
- if (this.#disconnects <= this.options.maxReconnects) {
87
- setTimeout(() => {
88
- this.#reconnect()
89
- }, this.options.reconnectTimeout)
90
- }
91
- })
92
-
93
- this.#webSocket.addEventListener('message', ({ data }) => {
94
- let json
95
- try {
96
- json = JSON.parse(data)
97
- } catch (error) {
98
- console.error(new Error(`Failed to parse RPC message: ${data}`, { cause: error }))
99
- return
100
- }
101
-
102
- if ('id' in json && json.id != null && this.#pendingRequests.has(json.id)) {
103
- const { resolve, timeout } = this.#pendingRequests.get(json.id)
104
-
105
- clearTimeout(timeout)
106
- resolve(json)
107
- } else if ('params' in json) {
108
- const { params } = json
109
- this.#subscriptions.forEach((subscription) => {
110
- if (
111
- subscription.subscriptionId === params.subscription &&
112
- params.subscription === subscription.subscriptionId
113
- ) {
114
- subscription.onMessage(params.result)
115
- }
116
- })
117
- }
118
- })
119
- })
120
-
121
- return this.#connectionPromise
122
- }
123
-
124
- async #reconnect() {
125
- this.#webSocket?.close()
126
- this.#connectionPromise = null
127
-
128
- return Promise.allSettled(
129
- [...this.#subscriptions].map((subscription) => subscription.subscribe(this))
130
- )
131
- }
132
-
133
- async subscribe(input) {
134
- const subscription = new RpcSubscription(input)
135
- this.#subscriptions.add(subscription)
136
- await subscription.subscribe(this)
137
- return () => subscription.unsubscribe(this)
138
- }
139
- }
140
-
141
- class RpcSubscription {
142
- subscriptionId = null
143
- input
144
- subscribed = false
145
-
146
- constructor(input) {
147
- this.input = input
148
- }
149
-
150
- onMessage(message) {
151
- if (this.subscribed) {
152
- this.input.onMessage(message)
153
- }
154
- }
155
-
156
- async unsubscribe(client) {
157
- const { subscriptionId } = this
158
- this.subscribed = false
159
- if (subscriptionId == null) return false
160
- this.subscriptionId = null
161
-
162
- return client.makeRequest(this.input.unsubscribe, [subscriptionId])
163
- }
164
-
165
- async subscribe(client) {
166
- this.subscriptionId = null
167
- this.subscribed = true
168
- const newSubscriptionId = await client.makeRequest(
169
- this.input.method,
170
- this.input.params,
171
- this.input.signal
172
- )
173
-
174
- if (this.subscribed) {
175
- this.subscriptionId = newSubscriptionId
176
- }
177
- }
178
- }
@@ -1,32 +0,0 @@
1
- /* eslint-disable sonarjs/no-nested-template-literals */
2
- class SuiClientError extends Error {}
3
-
4
- class ObjectError extends SuiClientError {
5
- constructor(code, message) {
6
- super(message)
7
- this.code = code
8
- }
9
-
10
- static fromResponse(response, objectId) {
11
- switch (response.code) {
12
- case 'notExists':
13
- return new ObjectError(response.code, `Object ${response.object_id} does not exist`)
14
- case 'dynamicFieldNotFound':
15
- return new ObjectError(
16
- response.code,
17
- `Dynamic field not found for object ${response.parent_object_id}`
18
- )
19
- case 'deleted':
20
- return new ObjectError(response.code, `Object ${response.object_id} has been deleted`)
21
- case 'displayError':
22
- return new ObjectError(response.code, `Display error: ${response.error}`)
23
- default:
24
- return new ObjectError(
25
- response.code,
26
- `Unknown error while loading object${objectId ? ` ${objectId}` : ''}`
27
- )
28
- }
29
- }
30
- }
31
- export { ObjectError, SuiClientError }
32
- // # sourceMappingURL=errors.js.map
@@ -1,5 +0,0 @@
1
- /* eslint-disable camelcase */
2
- export { ClientCache } from './cache.js'
3
- export { Experimental_CoreClient } from './core.js'
4
- export { Experimental_BaseClient } from './client.js'
5
- // # sourceMappingURL=index.js.map
@@ -1,90 +0,0 @@
1
- import { vendorLib } from '@exodus/sui-lib'
2
-
3
- import { TransactionDataBuilder } from '../../transactions/TransactionData.js'
4
-
5
- const { bcs } = vendorLib
6
-
7
- function parseTransactionBcs(bytes) {
8
- return {
9
- ...TransactionDataBuilder.fromBytes(bytes).snapshot(),
10
- bcs: bytes,
11
- }
12
- }
13
-
14
- function parseTransactionEffectsBcs(effects) {
15
- const parsed = bcs.TransactionEffects.parse(effects)
16
- switch (parsed.$kind) {
17
- case 'V1':
18
- return parseTransactionEffectsV1({ bytes: effects, effects: parsed.V1 })
19
- case 'V2':
20
- return parseTransactionEffectsV2({ bytes: effects, effects: parsed.V2 })
21
- default:
22
- throw new Error(`Unknown transaction effects version: ${parsed.$kind}`)
23
- }
24
- }
25
-
26
- function parseTransactionEffectsV1(_) {
27
- throw new Error('V1 effects are not supported yet')
28
- }
29
-
30
- function parseTransactionEffectsV2({ bytes, effects }) {
31
- const changedObjects = effects.changedObjects.map(([id, change]) => {
32
- return {
33
- id,
34
- inputState: change.inputState.$kind === 'Exist' ? 'Exists' : 'DoesNotExist',
35
- inputVersion: change.inputState.Exist?.[0][0] ?? null,
36
- inputDigest: change.inputState.Exist?.[0][1] ?? null,
37
- inputOwner: change.inputState.Exist?.[1] ?? null,
38
- outputState:
39
- change.outputState.$kind === 'NotExist' ? 'DoesNotExist' : change.outputState.$kind,
40
- outputVersion:
41
- change.outputState.$kind === 'PackageWrite'
42
- ? change.outputState.PackageWrite?.[0]
43
- : change.outputState.ObjectWrite
44
- ? effects.lamportVersion
45
- : null,
46
- outputDigest:
47
- change.outputState.$kind === 'PackageWrite'
48
- ? change.outputState.PackageWrite?.[1]
49
- : change.outputState.ObjectWrite?.[0] ?? null,
50
- outputOwner: change.outputState.ObjectWrite ? change.outputState.ObjectWrite[1] : null,
51
- idOperation: change.idOperation.$kind,
52
- }
53
- })
54
- return {
55
- bcs: bytes,
56
- digest: effects.transactionDigest,
57
- version: 2,
58
- status:
59
- effects.status.$kind === 'Success'
60
- ? {
61
- success: true,
62
- error: null,
63
- }
64
- : {
65
- success: false,
66
- // TODO: add command
67
- error: effects.status.Failed.error.$kind,
68
- },
69
- gasUsed: effects.gasUsed,
70
- transactionDigest: effects.transactionDigest,
71
- gasObject:
72
- effects.gasObjectIndex === null ? null : changedObjects[effects.gasObjectIndex] ?? null,
73
- eventsDigest: effects.eventsDigest,
74
- dependencies: effects.dependencies,
75
- lamportVersion: effects.lamportVersion,
76
- changedObjects,
77
- unchangedSharedObjects: effects.unchangedSharedObjects.map(([objectId, object]) => {
78
- return {
79
- kind: object.$kind,
80
- objectId,
81
- version: object.$kind === 'ReadOnlyRoot' ? object.ReadOnlyRoot[0] : object[object.$kind],
82
- digest: object.$kind === 'ReadOnlyRoot' ? object.ReadOnlyRoot[1] : null,
83
- }
84
- }),
85
- auxiliaryDataDigest: effects.auxDataDigest,
86
- }
87
- }
88
-
89
- export { parseTransactionBcs, parseTransactionEffectsBcs }
90
- // # sourceMappingURL=utils.js.map
@@ -1,22 +0,0 @@
1
- import { createObjectMethods } from './object.js'
2
- import { createPure } from './pure.js'
3
-
4
- const Arguments = {
5
- pure: createPure((value) => (tx) => tx.pure(value)),
6
- object: createObjectMethods((value) => (tx) => tx.object(value)),
7
- sharedObjectRef:
8
- (...args) =>
9
- (tx) =>
10
- tx.sharedObjectRef(...args),
11
- objectRef:
12
- (...args) =>
13
- (tx) =>
14
- tx.objectRef(...args),
15
- receivingRef:
16
- (...args) =>
17
- (tx) =>
18
- tx.receivingRef(...args),
19
- }
20
-
21
- export { Arguments }
22
- // # sourceMappingURL=Arguments.js.map
@@ -1,272 +0,0 @@
1
- /* eslint-disable no-sequences */
2
- import { vendorLib } from '@exodus/sui-lib'
3
-
4
- const { normalizeSuiAddress } = vendorLib.utils
5
-
6
- var __typeError = (msg) => {
7
- throw new TypeError(msg)
8
- }
9
-
10
- var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError('Cannot ' + msg)
11
- var __privateGet = (obj, member, getter) => (
12
- __accessCheck(obj, member, 'read from private field'), getter ? getter.call(obj) : member.get(obj)
13
- )
14
- var __privateAdd = (obj, member, value) =>
15
- member.has(obj)
16
- ? __typeError('Cannot add the same private member more than once')
17
- : member instanceof WeakSet
18
- ? member.add(obj)
19
- : member.set(obj, value)
20
- var __privateSet = (obj, member, value, setter) => (
21
- __accessCheck(obj, member, 'write to private field'),
22
- setter ? setter.call(obj, value) : member.set(obj, value),
23
- value
24
- )
25
- var _caches, _cache, _onEffects
26
-
27
- class AsyncCache {
28
- async getObject(id) {
29
- const [owned, shared] = await Promise.all([
30
- this.get('OwnedObject', id),
31
- this.get('SharedOrImmutableObject', id),
32
- ])
33
- return owned ?? shared ?? null
34
- }
35
-
36
- async getObjects(ids) {
37
- return Promise.all(ids.map((id) => this.getObject(id)))
38
- }
39
-
40
- async addObject(object) {
41
- if (object.owner) {
42
- await this.set('OwnedObject', object.objectId, object)
43
- } else {
44
- await this.set('SharedOrImmutableObject', object.objectId, object)
45
- }
46
-
47
- return object
48
- }
49
-
50
- async addObjects(objects) {
51
- await Promise.all(objects.map(async (object) => this.addObject(object)))
52
- }
53
-
54
- async deleteObject(id) {
55
- await Promise.all([this.delete('OwnedObject', id), this.delete('SharedOrImmutableObject', id)])
56
- }
57
-
58
- async deleteObjects(ids) {
59
- await Promise.all(ids.map((id) => this.deleteObject(id)))
60
- }
61
-
62
- async getMoveFunctionDefinition(ref) {
63
- const functionName = `${normalizeSuiAddress(ref.package)}::${ref.module}::${ref.function}`
64
- return this.get('MoveFunction', functionName)
65
- }
66
-
67
- async addMoveFunctionDefinition(functionEntry) {
68
- const pkg = normalizeSuiAddress(functionEntry.package)
69
- const functionName = `${pkg}::${functionEntry.module}::${functionEntry.function}`
70
- const entry = {
71
- ...functionEntry,
72
- package: pkg,
73
- }
74
- await this.set('MoveFunction', functionName, entry)
75
- return entry
76
- }
77
-
78
- async deleteMoveFunctionDefinition(ref) {
79
- const functionName = `${normalizeSuiAddress(ref.package)}::${ref.module}::${ref.function}`
80
- await this.delete('MoveFunction', functionName)
81
- }
82
-
83
- async getCustom(key) {
84
- return this.get('Custom', key)
85
- }
86
-
87
- async setCustom(key, value) {
88
- return this.set('Custom', key, value)
89
- }
90
-
91
- async deleteCustom(key) {
92
- return this.delete('Custom', key)
93
- }
94
- }
95
-
96
- class InMemoryCache extends AsyncCache {
97
- constructor() {
98
- super(...arguments)
99
- __privateAdd(this, _caches, {
100
- OwnedObject: /* @__PURE__ */ new Map(),
101
- SharedOrImmutableObject: /* @__PURE__ */ new Map(),
102
- MoveFunction: /* @__PURE__ */ new Map(),
103
- Custom: /* @__PURE__ */ new Map(),
104
- })
105
- }
106
-
107
- async get(type, key) {
108
- return __privateGet(this, _caches)[type].get(key) ?? null
109
- }
110
-
111
- async set(type, key, value) {
112
- __privateGet(this, _caches)[type].set(key, value)
113
- }
114
-
115
- async delete(type, key) {
116
- __privateGet(this, _caches)[type].delete(key)
117
- }
118
-
119
- async clear(type) {
120
- if (type) {
121
- __privateGet(this, _caches)[type].clear()
122
- } else {
123
- for (const cache of Object.values(__privateGet(this, _caches))) {
124
- cache.clear()
125
- }
126
- }
127
- }
128
- }
129
- _caches = new WeakMap()
130
-
131
- class ObjectCache {
132
- constructor({ cache = new InMemoryCache(), onEffects }) {
133
- __privateAdd(this, _cache)
134
- __privateAdd(this, _onEffects)
135
- __privateSet(this, _cache, cache)
136
- __privateSet(this, _onEffects, onEffects)
137
- }
138
-
139
- asPlugin() {
140
- return async (transactionData, _options, next) => {
141
- const unresolvedObjects = transactionData.inputs
142
- .filter((input) => input.UnresolvedObject)
143
- .map((input) => input.UnresolvedObject.objectId)
144
- // eslint-disable-next-line unicorn/no-await-expression-member
145
- const cached = (await __privateGet(this, _cache).getObjects(unresolvedObjects)).filter(
146
- (obj) => obj !== null
147
- )
148
- const byId = new Map(cached.map((obj) => [obj.objectId, obj]))
149
- for (const input of transactionData.inputs) {
150
- if (!input.UnresolvedObject) {
151
- continue
152
- }
153
-
154
- const cached2 = byId.get(input.UnresolvedObject.objectId)
155
- if (!cached2) {
156
- continue
157
- }
158
-
159
- if (cached2.initialSharedVersion && !input.UnresolvedObject.initialSharedVersion) {
160
- input.UnresolvedObject.initialSharedVersion = cached2.initialSharedVersion
161
- } else {
162
- if (cached2.version && !input.UnresolvedObject.version) {
163
- input.UnresolvedObject.version = cached2.version
164
- }
165
-
166
- if (cached2.digest && !input.UnresolvedObject.digest) {
167
- input.UnresolvedObject.digest = cached2.digest
168
- }
169
- }
170
- }
171
-
172
- await Promise.all(
173
- transactionData.commands.map(async (commands) => {
174
- if (commands.MoveCall) {
175
- const def = await this.getMoveFunctionDefinition({
176
- package: commands.MoveCall.package,
177
- module: commands.MoveCall.module,
178
- function: commands.MoveCall.function,
179
- })
180
- if (def) {
181
- // eslint-disable-next-line @exodus/mutable/no-param-reassign-prop-only
182
- commands.MoveCall._argumentTypes = def.parameters
183
- }
184
- }
185
- })
186
- )
187
- await next()
188
- await Promise.all(
189
- transactionData.commands.map(async (commands) => {
190
- if (commands.MoveCall?._argumentTypes) {
191
- await __privateGet(this, _cache).addMoveFunctionDefinition({
192
- package: commands.MoveCall.package,
193
- module: commands.MoveCall.module,
194
- function: commands.MoveCall.function,
195
- parameters: commands.MoveCall._argumentTypes,
196
- })
197
- }
198
- })
199
- )
200
- }
201
- }
202
-
203
- async clear() {
204
- await __privateGet(this, _cache).clear()
205
- }
206
-
207
- async getMoveFunctionDefinition(ref) {
208
- return __privateGet(this, _cache).getMoveFunctionDefinition(ref)
209
- }
210
-
211
- async getObjects(ids) {
212
- return __privateGet(this, _cache).getObjects(ids)
213
- }
214
-
215
- async deleteObjects(ids) {
216
- return __privateGet(this, _cache).deleteObjects(ids)
217
- }
218
-
219
- async clearOwnedObjects() {
220
- await __privateGet(this, _cache).clear('OwnedObject')
221
- }
222
-
223
- async clearCustom() {
224
- await __privateGet(this, _cache).clear('Custom')
225
- }
226
-
227
- async getCustom(key) {
228
- return __privateGet(this, _cache).getCustom(key)
229
- }
230
-
231
- async setCustom(key, value) {
232
- return __privateGet(this, _cache).setCustom(key, value)
233
- }
234
-
235
- async deleteCustom(key) {
236
- return __privateGet(this, _cache).deleteCustom(key)
237
- }
238
-
239
- async applyEffects(effects) {
240
- var _a
241
- if (!effects.V2) {
242
- throw new Error(`Unsupported transaction effects version ${effects.$kind}`)
243
- }
244
-
245
- const { lamportVersion, changedObjects } = effects.V2
246
- const deletedIds = []
247
- const addedObjects = []
248
- changedObjects.forEach(([id, change]) => {
249
- if (change.outputState.NotExist) {
250
- deletedIds.push(id)
251
- } else if (change.outputState.ObjectWrite) {
252
- const [digest, owner] = change.outputState.ObjectWrite
253
- addedObjects.push({
254
- objectId: id,
255
- digest,
256
- version: lamportVersion,
257
- owner: owner.AddressOwner ?? owner.ObjectOwner ?? null,
258
- initialSharedVersion: owner.Shared?.initialSharedVersion ?? null,
259
- })
260
- }
261
- })
262
- await Promise.all([
263
- __privateGet(this, _cache).addObjects(addedObjects),
264
- __privateGet(this, _cache).deleteObjects(deletedIds),
265
- (_a = __privateGet(this, _onEffects)) == null ? void 0 : _a.call(this, effects),
266
- ])
267
- }
268
- }
269
- _cache = new WeakMap()
270
- _onEffects = new WeakMap()
271
- export { AsyncCache, InMemoryCache, ObjectCache }
272
- // # sourceMappingURL=ObjectCache.js.map