suidouble 2.5.0 → 2.16.0
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.
- package/.claude/settings.local.json +7 -0
- package/README.md +222 -131
- package/index.js +0 -2
- package/lib/SuiCliCommands.js +18 -25
- package/lib/SuiCoin.js +79 -137
- package/lib/SuiCoins.js +41 -29
- package/lib/SuiCommonMethods.js +40 -3
- package/lib/SuiEvent.js +54 -6
- package/lib/SuiInBrowser.js +143 -15
- package/lib/SuiInBrowserAdapter.js +164 -37
- package/lib/SuiLocalTestValidator.js +76 -14
- package/lib/SuiMaster.js +335 -139
- package/lib/SuiMemoryObjectStorage.js +66 -73
- package/lib/SuiObject.js +128 -153
- package/lib/SuiPackage.js +292 -187
- package/lib/SuiPackageModule.js +176 -221
- package/lib/SuiPaginatedResponse.js +288 -25
- package/lib/SuiPseudoRandomAddress.js +29 -2
- package/lib/SuiTransaction.js +115 -70
- package/lib/SuiUtils.js +179 -127
- package/package.json +29 -13
- package/test/build_modules.test.js +41 -0
- package/test/coins.test.js +17 -16
- package/test/custom_transaction.test.js +167 -0
- package/test/event_listeners.test.js +171 -0
- package/test/failed_transaction.test.js +184 -0
- package/test/name_service.test.js +28 -0
- package/test/owned_objects.test.js +148 -0
- package/test/rpc.test.js +3 -6
- package/test/sui_in_browser.test.js +2 -2
- package/test/sui_master_basic.test.js +4 -5
- package/test/sui_master_onlocal.test.js +84 -22
- package/test/sui_object_properties.test.js +85 -0
- package/tsconfig.json +15 -0
- package/types/index.d.ts +15 -0
- package/types/lib/SuiCliCommands.d.ts +6 -0
- package/types/lib/SuiCoin.d.ts +183 -0
- package/types/lib/SuiCoins.d.ts +93 -0
- package/types/lib/SuiCommonMethods.d.ts +37 -0
- package/types/lib/SuiEvent.d.ts +95 -0
- package/types/lib/SuiInBrowser.d.ts +189 -0
- package/types/lib/SuiInBrowserAdapter.d.ts +167 -0
- package/types/lib/SuiLocalTestValidator.d.ts +92 -0
- package/types/lib/SuiMaster.d.ts +333 -0
- package/types/lib/SuiMemoryObjectStorage.d.ts +96 -0
- package/types/lib/SuiObject.d.ts +135 -0
- package/types/lib/SuiPackage.d.ts +233 -0
- package/types/lib/SuiPackageModule.d.ts +139 -0
- package/types/lib/SuiPaginatedResponse.d.ts +148 -0
- package/types/lib/SuiPseudoRandomAddress.d.ts +33 -0
- package/types/lib/SuiTransaction.d.ts +92 -0
- package/types/lib/SuiUtils.d.ts +152 -0
- package/types/lib/data/icons.d.ts +12 -0
- package/lib/SuiTestScenario.js +0 -169
- package/test/sui_test_scenario.test.js +0 -61
|
@@ -2,8 +2,14 @@ import SuiCommonMethods from './SuiCommonMethods.js';
|
|
|
2
2
|
import SuiObject from './SuiObject.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
6
|
-
|
|
5
|
+
* @typedef {import("./SuiMaster.js").default} SuiMaster
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* In-memory registry of `SuiObject` instances keyed by normalized address. One instance is
|
|
10
|
+
* created per connected chain (see `instanceOf`). Used by `SuiPackageModule` and friends to
|
|
11
|
+
* deduplicate object references across moveCall results and queries.
|
|
12
|
+
*
|
|
7
13
|
* Sample usage:
|
|
8
14
|
* ```
|
|
9
15
|
* suiMemoryObjectStorage.push(id);
|
|
@@ -17,26 +23,41 @@ export default class SuiMemoryObjectStorage extends SuiCommonMethods {
|
|
|
17
23
|
* SuiMemoryObjectStorage constructor
|
|
18
24
|
* @param {Object} params - Initialization parameters
|
|
19
25
|
* @param {SuiMaster} params.suiMaster - instance of SuiMaster
|
|
26
|
+
* @param {boolean} [params.debug]
|
|
20
27
|
*/
|
|
21
|
-
constructor(params
|
|
28
|
+
constructor(params) {
|
|
22
29
|
super(params);
|
|
23
30
|
|
|
31
|
+
/** @type {SuiMaster} */
|
|
24
32
|
this._suiMaster = params.suiMaster;
|
|
25
33
|
|
|
26
34
|
/** @type {Object.<string, SuiObject>} */
|
|
27
35
|
this._objects = {};
|
|
28
36
|
}
|
|
29
37
|
|
|
38
|
+
/** @returns {SuiObject[]} all stored SuiObjects, in insertion order */
|
|
30
39
|
asArray() {
|
|
31
40
|
return Object.values(this._objects);
|
|
32
41
|
}
|
|
33
42
|
|
|
43
|
+
/**
|
|
44
|
+
* Find the most-recently-pushed object whose `typeName` (short type name, e.g. "ChatTopMessage")
|
|
45
|
+
* matches `typeName`. Ordering is by each object's `constructedAt` timestamp.
|
|
46
|
+
*
|
|
47
|
+
* @param {string} typeName
|
|
48
|
+
* @returns {?SuiObject}
|
|
49
|
+
*/
|
|
34
50
|
findMostRecentByTypeName(typeName) {
|
|
35
51
|
return this.findMostRecent((object) => {
|
|
36
52
|
return (object.typeName == typeName);
|
|
37
53
|
});
|
|
38
54
|
}
|
|
39
55
|
|
|
56
|
+
/**
|
|
57
|
+
* Return the first stored object for which `filterFunction` returns truthy.
|
|
58
|
+
* @param {(obj: SuiObject) => boolean} filterFunction
|
|
59
|
+
* @returns {?SuiObject}
|
|
60
|
+
*/
|
|
40
61
|
find(filterFunction) {
|
|
41
62
|
for (const id in this._objects) {
|
|
42
63
|
if (filterFunction(this._objects[id])) {
|
|
@@ -47,6 +68,11 @@ export default class SuiMemoryObjectStorage extends SuiCommonMethods {
|
|
|
47
68
|
return null;
|
|
48
69
|
}
|
|
49
70
|
|
|
71
|
+
/**
|
|
72
|
+
* Return the most-recently-constructed object (by `constructedAt`) that matches `filterFunction`.
|
|
73
|
+
* @param {(obj: SuiObject) => boolean} filterFunction
|
|
74
|
+
* @returns {?SuiObject}
|
|
75
|
+
*/
|
|
50
76
|
findMostRecent(filterFunction) {
|
|
51
77
|
let mostRecentDate = null;
|
|
52
78
|
let mostRecentObject = null;
|
|
@@ -64,22 +90,26 @@ export default class SuiMemoryObjectStorage extends SuiCommonMethods {
|
|
|
64
90
|
}
|
|
65
91
|
|
|
66
92
|
/**
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
93
|
+
* Store a SuiObject, or wrap a raw `0x…` id in a new SuiObject and store it.
|
|
94
|
+
* If an object with the same address is already stored, it is returned as-is (no replacement).
|
|
95
|
+
*
|
|
96
|
+
* @param {SuiObject | string} suiObjectOrId - a SuiObject instance, or a `0x…` id string
|
|
97
|
+
* @returns {?SuiObject} the stored instance, or null if input didn't look like either
|
|
70
98
|
*/
|
|
71
99
|
push(suiObjectOrId) {
|
|
72
|
-
|
|
73
|
-
|
|
100
|
+
const a = /** @type {any} */ (suiObjectOrId);
|
|
101
|
+
if (a && a.address) {
|
|
102
|
+
const obj = /** @type {SuiObject} */ (a);
|
|
74
103
|
this._objects[obj.address] = obj;
|
|
75
104
|
|
|
76
105
|
return obj;
|
|
77
|
-
} else if (
|
|
78
|
-
|
|
79
|
-
|
|
106
|
+
} else if (a && (''+a).indexOf('0x') === 0) {
|
|
107
|
+
const id = /** @type {string} */ (a);
|
|
108
|
+
if (this._objects[id]) {
|
|
109
|
+
return this._objects[id];
|
|
80
110
|
}
|
|
81
111
|
|
|
82
|
-
const obj = new SuiObject({id
|
|
112
|
+
const obj = new SuiObject({id, suiMaster: this._suiMaster});
|
|
83
113
|
this._objects[obj.address] = obj;
|
|
84
114
|
|
|
85
115
|
return obj;
|
|
@@ -88,6 +118,11 @@ export default class SuiMemoryObjectStorage extends SuiCommonMethods {
|
|
|
88
118
|
return null;
|
|
89
119
|
}
|
|
90
120
|
|
|
121
|
+
/**
|
|
122
|
+
* Lookup by address. The address must already be in its normalized form (as produced by SuiObject).
|
|
123
|
+
* @param {string} address
|
|
124
|
+
* @returns {?SuiObject}
|
|
125
|
+
*/
|
|
91
126
|
byAddress(address) {
|
|
92
127
|
if (this._objects[address]) {
|
|
93
128
|
return this._objects[address];
|
|
@@ -95,78 +130,36 @@ export default class SuiMemoryObjectStorage extends SuiCommonMethods {
|
|
|
95
130
|
return null;
|
|
96
131
|
}
|
|
97
132
|
|
|
133
|
+
/**
|
|
134
|
+
* Refresh every non-deleted stored SuiObject's fields from chain.
|
|
135
|
+
* Delegates to `SuiMaster.getObjects(...)` which mutates the passed-in instances in place.
|
|
136
|
+
*
|
|
137
|
+
* @returns {Promise<SuiObject[]>}
|
|
138
|
+
*/
|
|
98
139
|
async fetchObjects() {
|
|
99
|
-
const objectsToFetch = this.asArray()
|
|
140
|
+
const objectsToFetch = this.asArray().filter((o) => !o.isDeleted);
|
|
141
|
+
if (!objectsToFetch.length) return [];
|
|
100
142
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
if (!object.isDeleted && objectIds.indexOf(object.address) === -1) {
|
|
104
|
-
objectIds.push(object.address);
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
this.log('querying details about', objectIds.length, 'objects');
|
|
109
|
-
this.log(objectIds);
|
|
110
|
-
|
|
111
|
-
let results = [];
|
|
112
|
-
const maxCountToFetch = 50;
|
|
113
|
-
for (let i = 0; i < objectIds.length; i += maxCountToFetch) {
|
|
114
|
-
const objectIdsSlice = objectIds.slice(i, i + maxCountToFetch);
|
|
115
|
-
|
|
116
|
-
let resultsSlice = [];
|
|
117
|
-
let consoleWarnMessage = null;
|
|
118
|
-
try {
|
|
119
|
-
const originalConsoleWarn = console.warn;
|
|
120
|
-
console.warn = (e)=>{
|
|
121
|
-
consoleWarnMessage = e;
|
|
122
|
-
};
|
|
123
|
-
resultsSlice = await this._suiMaster._client.multiGetObjects({
|
|
124
|
-
ids: objectIdsSlice,
|
|
125
|
-
options: { showType: true, showContent: true, showOwner: true, showDisplay: true, },
|
|
126
|
-
});
|
|
127
|
-
console.warn = originalConsoleWarn;
|
|
128
|
-
} catch(e) {
|
|
129
|
-
console.error(e);
|
|
130
|
-
}
|
|
143
|
+
this.log('querying details about', objectsToFetch.length, 'objects');
|
|
144
|
+
await this._suiMaster.getObjects(objectsToFetch);
|
|
131
145
|
|
|
132
|
-
|
|
133
|
-
this.log('got', resultsSlice.length, 'objects but with warning (ok, but probably it is different client vs rpc versions)');
|
|
134
|
-
} else {
|
|
135
|
-
this.log('got', resultsSlice.length, 'objects');
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
if (resultsSlice && resultsSlice.length) {
|
|
139
|
-
results = results.concat(resultsSlice);
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
for (const object of objectsToFetch) {
|
|
144
|
-
const foundInResults = results.find(element => object.idEquals(element?.data?.objectId));
|
|
145
|
-
if (foundInResults) {
|
|
146
|
-
object.tryToFillDataFromObjectChange(foundInResults);
|
|
147
|
-
// this.log('got updates for object', object.address, object.fields);
|
|
148
|
-
} else {
|
|
149
|
-
// object is removed?
|
|
150
|
-
const foundInRemoved = results.find(element => (element?.error?.code == 'deleted' && object.idEquals(element?.error?.object_id)));
|
|
151
|
-
if (foundInRemoved) {
|
|
152
|
-
object.markAsDeleted();
|
|
153
|
-
} else {
|
|
154
|
-
this.log('not found in results', object);
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
}
|
|
146
|
+
return objectsToFetch;
|
|
158
147
|
}
|
|
159
148
|
|
|
160
149
|
static _instances = {};
|
|
161
150
|
|
|
162
151
|
/**
|
|
163
|
-
*
|
|
164
|
-
*
|
|
152
|
+
* Return (and lazily create) a shared SuiMemoryObjectStorage keyed by `validatorId`.
|
|
153
|
+
* Typically `validatorId` is the connected chain name (`sui:mainnet`, `sui:localnet`, …) so that
|
|
154
|
+
* objects from different chains stay isolated.
|
|
155
|
+
*
|
|
156
|
+
* @param {string} validatorId - identifier for the singleton slot (chain name by convention)
|
|
157
|
+
* @param {Object} params - Initialization parameters used only on first creation for that slot
|
|
165
158
|
* @param {SuiMaster} params.suiMaster - instance of SuiMaster
|
|
166
|
-
*
|
|
159
|
+
* @param {boolean} [params.debug]
|
|
167
160
|
* @returns {SuiMemoryObjectStorage}
|
|
168
161
|
*/
|
|
169
|
-
static instanceOf(validatorId, params
|
|
162
|
+
static instanceOf(validatorId, params) {
|
|
170
163
|
if (SuiMemoryObjectStorage._instances[validatorId]) {
|
|
171
164
|
return SuiMemoryObjectStorage._instances[validatorId];
|
|
172
165
|
}
|
package/lib/SuiObject.js
CHANGED
|
@@ -2,6 +2,9 @@ import SuiCommonMethods from './SuiCommonMethods.js';
|
|
|
2
2
|
import SuiPaginatedResponse from './SuiPaginatedResponse.js';
|
|
3
3
|
import { normalizeSuiAddress } from './SuiUtils.js';
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* @import { SuiClientTypes } from "@mysten/sui/client"
|
|
7
|
+
*/
|
|
5
8
|
/**
|
|
6
9
|
* @typedef {import("./SuiMaster.js").default} SuiMaster
|
|
7
10
|
*/
|
|
@@ -12,23 +15,27 @@ export default class SuiObject extends SuiCommonMethods {
|
|
|
12
15
|
*
|
|
13
16
|
* @param {Object} params - parameters
|
|
14
17
|
* @param {SuiMaster} params.suiMaster - instance of SuiMaster
|
|
18
|
+
* @param {SuiClientTypes.Object} [params.raw] - raw data from api
|
|
15
19
|
* @param {?string} [params.id] - ID or address on the sui blockchain
|
|
20
|
+
* @param {string|number} [params.version] - object version
|
|
21
|
+
* @param {?string} [params.type] - fully-qualified Move type string
|
|
22
|
+
* @param {boolean} [params.debug]
|
|
16
23
|
*/
|
|
17
|
-
constructor(params
|
|
24
|
+
constructor(params) {
|
|
18
25
|
super(params);
|
|
19
26
|
|
|
20
27
|
/** @type {SuiMaster} */
|
|
21
28
|
this._suiMaster = params.suiMaster;
|
|
22
29
|
if (!this._suiMaster) {
|
|
23
|
-
throw new Error('suiMaster is
|
|
30
|
+
throw new Error('suiMaster is required for SuiObject');
|
|
24
31
|
}
|
|
25
32
|
|
|
26
|
-
/** @type {string} */
|
|
33
|
+
/** @type {?string} */
|
|
27
34
|
this._id = params.id || null;
|
|
28
|
-
|
|
29
|
-
|
|
35
|
+
/** @type {?number} */
|
|
36
|
+
this._version = params.version != null ? Number(params.version) : null;
|
|
30
37
|
|
|
31
|
-
/** @type {string} */
|
|
38
|
+
/** @type {?string} */
|
|
32
39
|
this._type = params.type || null;
|
|
33
40
|
|
|
34
41
|
this._fields = {}; // on-chain fields on the object
|
|
@@ -41,42 +48,84 @@ export default class SuiObject extends SuiCommonMethods {
|
|
|
41
48
|
|
|
42
49
|
this._localProperties = {}; // object to store some local data for you to help with your local calculations, no interaction with blockchain
|
|
43
50
|
|
|
44
|
-
// this._ownerAddress = null;
|
|
45
|
-
|
|
46
51
|
this._isDeleted = false;
|
|
47
52
|
|
|
48
|
-
if (params.
|
|
49
|
-
this.
|
|
53
|
+
if (params.raw) {
|
|
54
|
+
this.fillDataFromApi(params.raw);
|
|
50
55
|
}
|
|
51
56
|
|
|
52
57
|
this._constructedAt = new Date(); // just a helpful data so we can sort later when trying to find most recent item in different modules
|
|
53
58
|
}
|
|
54
59
|
|
|
60
|
+
/**
|
|
61
|
+
* Fill local properties from raw SuiClientTypes.Object api response
|
|
62
|
+
* @param {SuiClientTypes.Object} raw
|
|
63
|
+
*/
|
|
64
|
+
fillDataFromApi(raw) {
|
|
65
|
+
if (!raw) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (raw.objectId && !this._id) {
|
|
70
|
+
this._id = raw.objectId;
|
|
71
|
+
}
|
|
72
|
+
if (raw.version !== undefined && raw.version !== null) {
|
|
73
|
+
this._version = Number(raw.version);
|
|
74
|
+
}
|
|
75
|
+
if (raw.type) {
|
|
76
|
+
this._type = raw.type;
|
|
77
|
+
}
|
|
78
|
+
if (raw.owner) {
|
|
79
|
+
this._owner = raw.owner;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (raw.json && typeof raw.json === 'object') {
|
|
83
|
+
this._fields = raw.json;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (raw.display && raw.display.output) {
|
|
87
|
+
this._display = raw.display.output;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/** @returns {Date} timestamp when this JS object was instantiated (useful for sorting by recency) */
|
|
55
92
|
get constructedAt() {
|
|
56
93
|
return this._constructedAt;
|
|
57
94
|
}
|
|
58
95
|
|
|
96
|
+
/**
|
|
97
|
+
* Compare two Sui object IDs after normalisation.
|
|
98
|
+
* @param {string} id1
|
|
99
|
+
* @param {string} id2
|
|
100
|
+
* @returns {boolean}
|
|
101
|
+
*/
|
|
59
102
|
static idsEqual(id1, id2) {
|
|
60
103
|
return (normalizeSuiAddress(id1) === normalizeSuiAddress(id2));
|
|
61
104
|
}
|
|
62
105
|
|
|
106
|
+
/** @returns {boolean} true if this object has been marked deleted */
|
|
63
107
|
get isDeleted() {
|
|
64
108
|
return this._isDeleted;
|
|
65
109
|
}
|
|
66
110
|
|
|
111
|
+
/** @returns {boolean} true if the object is shared (owned by the network) */
|
|
67
112
|
get isShared() {
|
|
68
|
-
return (this._owner && this._owner.Shared);
|
|
113
|
+
return !!(this._owner && (this._owner.Shared || this._owner.$kind === 'Shared'));
|
|
69
114
|
}
|
|
70
115
|
|
|
116
|
+
/** @returns {boolean} true if the object is immutable (frozen) */
|
|
71
117
|
get isImmutable() {
|
|
72
|
-
return (this._owner && this._owner
|
|
118
|
+
return !!(this._owner && (this._owner === 'Immutable' || this._owner.$kind === 'Immutable'));
|
|
73
119
|
}
|
|
74
120
|
|
|
121
|
+
/**
|
|
122
|
+
* Check whether this object is address-owned by the given address or SuiObject.
|
|
123
|
+
* @param {string | SuiObject} addressOrSuiObject
|
|
124
|
+
* @returns {boolean}
|
|
125
|
+
*/
|
|
75
126
|
isOwnedBy(addressOrSuiObject) {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
toId = toId.id;
|
|
79
|
-
}
|
|
127
|
+
const a = /** @type {any} */ (addressOrSuiObject);
|
|
128
|
+
const toId = a.id ?? a;
|
|
80
129
|
|
|
81
130
|
if (this._owner && this._owner.AddressOwner && this._owner.AddressOwner == toId) {
|
|
82
131
|
return true;
|
|
@@ -85,30 +134,39 @@ export default class SuiObject extends SuiCommonMethods {
|
|
|
85
134
|
return false;
|
|
86
135
|
}
|
|
87
136
|
|
|
137
|
+
/** Mark this object as deleted on-chain and set `isDeleted` to true. */
|
|
88
138
|
markAsDeleted() {
|
|
89
139
|
this._isDeleted = true;
|
|
90
140
|
}
|
|
91
141
|
|
|
142
|
+
/** @returns {?string} raw object id as stored (not normalised) */
|
|
92
143
|
get id() {
|
|
93
144
|
return this._id;
|
|
94
145
|
}
|
|
95
146
|
|
|
147
|
+
/** @returns {?string} fully-qualified Move type string, e.g. `'0x2::coin::Coin<0x2::sui::SUI>'` */
|
|
96
148
|
get type() {
|
|
97
149
|
return this._type;
|
|
98
150
|
}
|
|
99
151
|
|
|
100
152
|
/**
|
|
101
|
-
*
|
|
153
|
+
* Short type name — last `::` segment without `<T…>` suffix.
|
|
154
|
+
* @returns {?string} e.g. `'ChatTopMessage'`
|
|
102
155
|
*/
|
|
103
156
|
get typeName() {
|
|
104
157
|
return this._type ? (''+this._type).split('<')[0].split('::').pop() : null;
|
|
105
158
|
}
|
|
106
159
|
|
|
160
|
+
/**
|
|
161
|
+
* Check whether this object's normalised address equals `toId`.
|
|
162
|
+
* @param {string} toId
|
|
163
|
+
* @returns {boolean}
|
|
164
|
+
*/
|
|
107
165
|
idEquals(toId) {
|
|
108
166
|
if (!toId) {
|
|
109
167
|
return false;
|
|
110
168
|
}
|
|
111
|
-
|
|
169
|
+
|
|
112
170
|
const thisAddress = this.address;
|
|
113
171
|
if (thisAddress && thisAddress === normalizeSuiAddress(toId)) {
|
|
114
172
|
return true;
|
|
@@ -116,6 +174,10 @@ export default class SuiObject extends SuiCommonMethods {
|
|
|
116
174
|
return false;
|
|
117
175
|
}
|
|
118
176
|
|
|
177
|
+
/**
|
|
178
|
+
* Normalised 0x-padded Sui address, or null if the id is invalid.
|
|
179
|
+
* @returns {?string}
|
|
180
|
+
*/
|
|
119
181
|
get address() {
|
|
120
182
|
try {
|
|
121
183
|
return normalizeSuiAddress(this._id);
|
|
@@ -124,99 +186,49 @@ export default class SuiObject extends SuiCommonMethods {
|
|
|
124
186
|
}
|
|
125
187
|
}
|
|
126
188
|
|
|
189
|
+
/** @returns {Object} on-chain Move struct fields (populated by `fillDataFromApi` or `fetchFields`) */
|
|
127
190
|
get fields() {
|
|
128
191
|
return this._fields;
|
|
129
192
|
}
|
|
130
193
|
|
|
194
|
+
/** @returns {Object} Display template rendered output (populated by `fillDataFromApi` or `fetchFields`) */
|
|
131
195
|
get display() {
|
|
132
196
|
return this._display;
|
|
133
197
|
}
|
|
134
198
|
|
|
199
|
+
/** @returns {Object} local-only property bag — never sent to chain, for caller convenience */
|
|
135
200
|
get localProperties() {
|
|
136
201
|
return this._localProperties;
|
|
137
202
|
}
|
|
138
203
|
|
|
204
|
+
/** @returns {?number} object version (lamport timestamp), or null before `fetchFields` */
|
|
139
205
|
get version() {
|
|
140
206
|
return this._version;
|
|
141
207
|
}
|
|
142
208
|
|
|
143
209
|
/**
|
|
144
|
-
*
|
|
145
|
-
*
|
|
146
|
-
*
|
|
147
|
-
* @param {
|
|
148
|
-
* @
|
|
210
|
+
* Fetch transactions that interacted with this object, via GraphQL.
|
|
211
|
+
*
|
|
212
|
+
* @param {Object} [params]
|
|
213
|
+
* @param {number} [params.limit=10]
|
|
214
|
+
* @param {string} [params.order]
|
|
215
|
+
* @returns {Promise<SuiPaginatedResponse>}
|
|
149
216
|
*/
|
|
150
|
-
async
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
}
|
|
154
|
-
v = Number(v);
|
|
155
|
-
|
|
156
|
-
const result = await this._suiMaster._client.tryGetPastObject({
|
|
157
|
-
version: (v),
|
|
158
|
-
id: this.address,
|
|
159
|
-
options: {
|
|
160
|
-
showType: true,
|
|
161
|
-
showContent: true,
|
|
162
|
-
showOwner: true,
|
|
163
|
-
showDisplay: true,
|
|
164
|
-
"showPreviousTransaction": true,
|
|
165
|
-
"showBcs": false,
|
|
166
|
-
"showStorageRebate": true
|
|
167
|
-
},
|
|
168
|
-
});
|
|
169
|
-
|
|
170
|
-
if (result && result.details && result.details.objectId) {
|
|
171
|
-
const pastObject = new SuiObject({
|
|
172
|
-
suiMaster: this._suiMaster,
|
|
173
|
-
debug: this._debug,
|
|
174
|
-
objectChange: result.details,
|
|
175
|
-
});
|
|
176
|
-
|
|
177
|
-
return pastObject;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
return null;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
async queryTransactionBlocks(params = {}) {
|
|
184
|
-
// @todo: InputObject / ChangedObject ? make separate function or a param here?
|
|
185
|
-
const queryParams = {
|
|
186
|
-
filter: {
|
|
187
|
-
InputObject: this.address,
|
|
188
|
-
},
|
|
217
|
+
async fetchTransactions(params = {}) {
|
|
218
|
+
return await this._suiMaster.fetchTransactions({
|
|
219
|
+
affectedObject: this.address,
|
|
189
220
|
limit: params.limit || 10,
|
|
190
|
-
options: {
|
|
191
|
-
/* Whether to show transaction input data. Default to be false. */
|
|
192
|
-
showInput: true,
|
|
193
|
-
/* Whether to show transaction effects. Default to be false. */
|
|
194
|
-
showEffects: true,
|
|
195
|
-
/* Whether to show transaction events. Default to be false. */
|
|
196
|
-
showEvents: true,
|
|
197
|
-
/* Whether to show object changes. Default to be false. */
|
|
198
|
-
showObjectChanges: true,
|
|
199
|
-
/* Whether to show coin balance changes. Default to be false. */
|
|
200
|
-
showBalanceChanges: true,
|
|
201
|
-
showContent: true,
|
|
202
|
-
showOwner: true,
|
|
203
|
-
showDisplay: true,
|
|
204
|
-
},
|
|
205
|
-
};
|
|
206
|
-
|
|
207
|
-
const paginatedResponse = new SuiPaginatedResponse({
|
|
208
|
-
debug: this._debug,
|
|
209
|
-
suiMaster: this._suiMaster,
|
|
210
|
-
params: queryParams,
|
|
211
|
-
method: 'queryTransactionBlocks',
|
|
212
221
|
order: params.order,
|
|
213
222
|
});
|
|
214
|
-
|
|
215
|
-
await paginatedResponse.fetch();
|
|
216
|
-
|
|
217
|
-
return paginatedResponse;
|
|
218
223
|
}
|
|
219
224
|
|
|
225
|
+
/**
|
|
226
|
+
* Fetch dynamic fields owned by this object, paginated.
|
|
227
|
+
* @param {Object} [params]
|
|
228
|
+
* @param {number} [params.limit=50]
|
|
229
|
+
* @param {string} [params.order]
|
|
230
|
+
* @returns {Promise<SuiPaginatedResponse>}
|
|
231
|
+
*/
|
|
220
232
|
async getDynamicFields(params = {}) {
|
|
221
233
|
const queryParams = {
|
|
222
234
|
parentId: this.address,
|
|
@@ -227,7 +239,7 @@ export default class SuiObject extends SuiCommonMethods {
|
|
|
227
239
|
debug: this._debug,
|
|
228
240
|
suiMaster: this._suiMaster,
|
|
229
241
|
params: queryParams,
|
|
230
|
-
method: '
|
|
242
|
+
method: 'listDynamicFields',
|
|
231
243
|
order: params.order,
|
|
232
244
|
});
|
|
233
245
|
|
|
@@ -236,22 +248,17 @@ export default class SuiObject extends SuiCommonMethods {
|
|
|
236
248
|
return paginatedResponse;
|
|
237
249
|
}
|
|
238
250
|
|
|
251
|
+
/**
|
|
252
|
+
* Fetch full field data for this object from chain and merge via `replaceWithSuiObjectIfNeeded`.
|
|
253
|
+
* Populates `fields`, `display`, `type`, and `version` if not already filled.
|
|
254
|
+
* @returns {Promise<this>}
|
|
255
|
+
*/
|
|
239
256
|
async fetchFields() {
|
|
240
|
-
const
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
showType: true,
|
|
244
|
-
showContent: true,
|
|
245
|
-
showOwner: true,
|
|
246
|
-
showDisplay: true,
|
|
247
|
-
"showPreviousTransaction": true,
|
|
248
|
-
"showBcs": false,
|
|
249
|
-
"showStorageRebate": true
|
|
250
|
-
},
|
|
251
|
-
});
|
|
252
|
-
if (result && result.data) {
|
|
253
|
-
this.tryToFillDataFromObjectChange(result.data);
|
|
257
|
+
const fetched = await this._suiMaster.getObject(this.address);
|
|
258
|
+
if (fetched) {
|
|
259
|
+
this.replaceWithSuiObjectIfNeeded(fetched);
|
|
254
260
|
}
|
|
261
|
+
return this;
|
|
255
262
|
}
|
|
256
263
|
|
|
257
264
|
/**
|
|
@@ -283,61 +290,29 @@ export default class SuiObject extends SuiCommonMethods {
|
|
|
283
290
|
return true;
|
|
284
291
|
}
|
|
285
292
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
* @param {Object} objectChange
|
|
292
|
-
*/
|
|
293
|
-
tryToFillDataFromObjectChange(objectChange) {
|
|
294
|
-
if (!objectChange.objectId && objectChange.data && objectChange.data.objectId) {
|
|
295
|
-
objectChange = objectChange.data;
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
if (objectChange.type && objectChange.type == 'deleted') {
|
|
299
|
-
this.markAsDeleted();
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
// basic fields. Available both in getObject and in results of .moveCall
|
|
303
|
-
if (objectChange.objectId) {
|
|
304
|
-
if (!this._id) {
|
|
305
|
-
this._id = objectChange.objectId;
|
|
306
|
-
} else if (!this.idEquals(objectChange.objectId)) {
|
|
307
|
-
throw new Error('Trying to fill from different object');
|
|
308
|
-
}
|
|
309
|
-
if (objectChange.type && !this._type) {
|
|
310
|
-
this._type = objectChange.type;
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
if (objectChange.version) {
|
|
314
|
-
this._version = BigInt(objectChange.version);
|
|
293
|
+
// same or older version — still fill any locally-empty slots
|
|
294
|
+
let filled = false;
|
|
295
|
+
if (!this._type && suiObject.type) {
|
|
296
|
+
this._type = suiObject.type;
|
|
297
|
+
filled = true;
|
|
315
298
|
}
|
|
316
|
-
if (
|
|
317
|
-
this.
|
|
299
|
+
if (!this._owner && suiObject._owner) {
|
|
300
|
+
this._owner = suiObject._owner;
|
|
301
|
+
filled = true;
|
|
318
302
|
}
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
if (objectChange?.content?.fields) {
|
|
323
|
-
for (const key in objectChange?.content?.fields) {
|
|
324
|
-
if (key !== 'id') {
|
|
325
|
-
this._fields[key] = objectChange.content.fields[key];
|
|
326
|
-
}
|
|
327
|
-
}
|
|
303
|
+
if ((!this._fields || Object.keys(this._fields).length === 0) && suiObject._fields) {
|
|
304
|
+
this._fields = suiObject._fields;
|
|
305
|
+
filled = true;
|
|
328
306
|
}
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
for (const key in objectChange?.display?.data) {
|
|
333
|
-
this._display[key] = objectChange.display.data[key];
|
|
334
|
-
}
|
|
307
|
+
if ((!this._display || Object.keys(this._display).length === 0) && suiObject._display) {
|
|
308
|
+
this._display = suiObject._display;
|
|
309
|
+
filled = true;
|
|
335
310
|
}
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
this._owner = objectChange.owner;
|
|
311
|
+
if (!this._version && suiObject.version) {
|
|
312
|
+
this._version = suiObject.version;
|
|
313
|
+
filled = true;
|
|
340
314
|
}
|
|
341
315
|
|
|
316
|
+
return filled;
|
|
342
317
|
}
|
|
343
318
|
};
|