suidouble 0.0.3
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/LICENSE +201 -0
- package/README.md +302 -0
- package/index.js +9 -0
- package/lib/SuiCliCommands.js +67 -0
- package/lib/SuiCommonMethods.js +44 -0
- package/lib/SuiEvent.js +35 -0
- package/lib/SuiInBrowser.js +284 -0
- package/lib/SuiInBrowserAdapter.js +181 -0
- package/lib/SuiLocalTestValidator.js +93 -0
- package/lib/SuiMaster.js +199 -0
- package/lib/SuiMemoryObjectStorage.js +69 -0
- package/lib/SuiObject.js +211 -0
- package/lib/SuiPackage.js +520 -0
- package/lib/SuiPackageModule.js +314 -0
- package/lib/SuiPaginatedResponse.js +76 -0
- package/lib/SuiPseudoRandomAddress.js +35 -0
- package/lib/SuiTestScenario.js +161 -0
- package/lib/data/icons.json +8 -0
- package/package.json +15 -0
package/lib/SuiMaster.js
ADDED
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
const sui = require('@mysten/sui.js');
|
|
2
|
+
const SuiCommonMethods = require('./SuiCommonMethods.js');
|
|
3
|
+
const SuiPackage = require('./SuiPackage.js');
|
|
4
|
+
const SuiPseudoRandomAddress = require('./SuiPseudoRandomAddress.js');
|
|
5
|
+
const SuiMemoryObjectStorage = require('./SuiMemoryObjectStorage.js');
|
|
6
|
+
|
|
7
|
+
class SuiMaster extends SuiCommonMethods {
|
|
8
|
+
constructor(params = {}) {
|
|
9
|
+
super(params);
|
|
10
|
+
|
|
11
|
+
// quick value to differenciate instances (if there're few) in logs
|
|
12
|
+
SuiMaster.instancesCount++;
|
|
13
|
+
this._instanceN = SuiMaster.instancesCount;
|
|
14
|
+
|
|
15
|
+
this._signer = null;
|
|
16
|
+
this._keypair = null;
|
|
17
|
+
|
|
18
|
+
if (params.signer) {
|
|
19
|
+
this._signer = params.signer;
|
|
20
|
+
} else if (params.keypair) {
|
|
21
|
+
this._keypair = params.keypair;
|
|
22
|
+
} else if (params.phrase) {
|
|
23
|
+
this._keypair = sui.Ed25519Keypair.deriveKeypair(params.phrase);
|
|
24
|
+
|
|
25
|
+
this.log('goint to use keypair of', this._keypair.getPublicKey().toSuiAddress());
|
|
26
|
+
} else if (params.as) {
|
|
27
|
+
// generate pseudo-random keypair
|
|
28
|
+
this._keypair = SuiPseudoRandomAddress.stringToKeyPair(params.as);
|
|
29
|
+
|
|
30
|
+
this.log('goint to use keypair of', this._keypair.getPublicKey().toSuiAddress());
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
this._provider = null;
|
|
34
|
+
this._providerName = null;
|
|
35
|
+
if (params.provider) {
|
|
36
|
+
if (params.provider == 'local' || (params.provider.constructor && params.provider.constructor.name && params.provider.constructor.name == 'SuiLocalTestValidator')) {
|
|
37
|
+
this._provider = new sui.JsonRpcProvider(sui.localnetConnection);
|
|
38
|
+
this._providerName = 'local';
|
|
39
|
+
} else if (params.provider == 'test' || params.provider == 'testnet') {
|
|
40
|
+
this._provider = new sui.JsonRpcProvider(sui.testnetConnection);
|
|
41
|
+
this._providerName = 'test';
|
|
42
|
+
} else if (params.provider == 'dev' || params.provider == 'devnet') {
|
|
43
|
+
this._provider = new sui.JsonRpcProvider(sui.devnetConnection);
|
|
44
|
+
this._providerName = 'dev';
|
|
45
|
+
} else {
|
|
46
|
+
if (params.provider && params.provider.connection && params.provider.connection.fullnode) {
|
|
47
|
+
this._provider = params.provider;
|
|
48
|
+
this._providerName = params.provider.connection.fullnode;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (!this._provider) {
|
|
54
|
+
throw new Error('Can not do anything without provider. Set params.provider at least to `local`');
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// we are differient single instances of object storage by provider name (so we can separate like devnet-testnet entities if needed)
|
|
58
|
+
this._objectStorage = SuiMemoryObjectStorage.instanceOf(this._providerName, {
|
|
59
|
+
debug: this._debug,
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
this._initialized = false;
|
|
63
|
+
|
|
64
|
+
this._address = null;
|
|
65
|
+
|
|
66
|
+
this._packages = {};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
get objectStorage() {
|
|
70
|
+
return this._objectStorage;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
get instanceN() {
|
|
74
|
+
return this._instanceN;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
static instancesCount = 0;
|
|
78
|
+
|
|
79
|
+
get provider() {
|
|
80
|
+
return this._provider;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
get address() {
|
|
84
|
+
return this._address;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
get signer() {
|
|
88
|
+
return this._signer;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
package(params = {}) {
|
|
92
|
+
return this.addPackage(params);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
addPackage(params = {}) {
|
|
96
|
+
if (params.id && this._packages[params.id]) {
|
|
97
|
+
return this._packages[params.id];
|
|
98
|
+
}
|
|
99
|
+
const suiPackage = new SuiPackage({
|
|
100
|
+
...params,
|
|
101
|
+
debug: this._debug,
|
|
102
|
+
suiMaster: this,
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
if (params.id) {
|
|
106
|
+
this._packages[params.id] = suiPackage;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return suiPackage;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
async getProvider() {
|
|
113
|
+
await this.initialize();
|
|
114
|
+
return this._provider;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
async initialize() {
|
|
118
|
+
if (this._initialized) {
|
|
119
|
+
return true;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
this.log('initializing...');
|
|
123
|
+
|
|
124
|
+
this._initialized = true;
|
|
125
|
+
|
|
126
|
+
// this._keypair = sui.Ed25519Keypair.deriveKeypair(this._phrase);
|
|
127
|
+
if (!this._signer && this._keypair) { // we may optionally go without signer, to work in read-only mode
|
|
128
|
+
this._signer = new sui.RawSigner(this._keypair, this._provider);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// const publicKey = this._keypair.getPublicKey();
|
|
132
|
+
// this._address = publicKey.toSuiAddress();
|
|
133
|
+
if (this._signer) {
|
|
134
|
+
this._address = await this._signer.getAddress();
|
|
135
|
+
// console.log(this._signer);
|
|
136
|
+
// console.log(this._providerName);
|
|
137
|
+
this.log('initialized. connected as', this._address);
|
|
138
|
+
} else {
|
|
139
|
+
this.log('initialized in read-only mode.');
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
return true;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
async requestSuiFromFaucet() {
|
|
147
|
+
await this.initialize();
|
|
148
|
+
|
|
149
|
+
this.log('requesting sui from faucet...');
|
|
150
|
+
|
|
151
|
+
let res = null;
|
|
152
|
+
try {
|
|
153
|
+
res = await this._provider.requestSuiFromFaucet(this._address);
|
|
154
|
+
} catch (e) {
|
|
155
|
+
this.log('error', e);
|
|
156
|
+
res = null;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
let amount = BigInt(0);
|
|
160
|
+
let objectsCount = 0;
|
|
161
|
+
|
|
162
|
+
if (res && res.transferredGasObjects) {
|
|
163
|
+
for (let transferredGasObject of res.transferredGasObjects) {
|
|
164
|
+
amount += BigInt(transferredGasObject.amount);
|
|
165
|
+
objectsCount++;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
this.log('got from faucet', amount, 'MIST in', objectsCount, 'objects');
|
|
170
|
+
|
|
171
|
+
return amount;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
async getBalance(coinType = '0x2::sui::SUI') {
|
|
175
|
+
await this.initialize();
|
|
176
|
+
|
|
177
|
+
this.log('requesting balance of coin', coinType, '...');
|
|
178
|
+
|
|
179
|
+
let res = null;
|
|
180
|
+
try {
|
|
181
|
+
res = await this._provider.getBalance({owner: this._address, coinType});
|
|
182
|
+
} catch (e) {
|
|
183
|
+
this.log('error', e);
|
|
184
|
+
res = null;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
let ret = BigInt(0);
|
|
188
|
+
if (res && res.totalBalance) {
|
|
189
|
+
ret = BigInt(res.totalBalance);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
this.log('balance of', coinType, 'is', ret);
|
|
193
|
+
return ret;
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
module.exports = SuiMaster;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
const SuiCommonMethods = require('./SuiCommonMethods.js');
|
|
2
|
+
|
|
3
|
+
class SuiMemoryObjectStorage extends SuiCommonMethods {
|
|
4
|
+
constructor(params = {}) {
|
|
5
|
+
super(params);
|
|
6
|
+
|
|
7
|
+
this._objects = {};
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
asArray() {
|
|
11
|
+
return Object.values(this._objects);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
find(filterFunction) {
|
|
15
|
+
for (const id in this._objects) {
|
|
16
|
+
if (filterFunction(this._objects[id])) {
|
|
17
|
+
return this._objects[id];
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
findMostRecent(filterFunction) {
|
|
25
|
+
let mostRecentDate = null;
|
|
26
|
+
let mostRecentObject = null;
|
|
27
|
+
|
|
28
|
+
for (const id in this._objects) {
|
|
29
|
+
if (filterFunction(this._objects[id])) {
|
|
30
|
+
if (!mostRecentDate || (mostRecentDate.getTime() <= this._objects[id].constructedAt.getTime())) {
|
|
31
|
+
mostRecentDate = this._objects[id].constructedAt;
|
|
32
|
+
mostRecentObject = this._objects[id];
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return mostRecentObject;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
push(object) {
|
|
41
|
+
if (object.address) {
|
|
42
|
+
this._objects[object.address] = object;
|
|
43
|
+
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
byAddress(address) {
|
|
51
|
+
if (this._objects[address]) {
|
|
52
|
+
return this._objects[address];
|
|
53
|
+
}
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
static _instances = {};
|
|
58
|
+
|
|
59
|
+
static instanceOf(validatorId, params = {}) {
|
|
60
|
+
if (SuiMemoryObjectStorage._instances[validatorId]) {
|
|
61
|
+
return SuiMemoryObjectStorage._instances[validatorId];
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
SuiMemoryObjectStorage._instances[validatorId] = new SuiMemoryObjectStorage(params);
|
|
65
|
+
return SuiMemoryObjectStorage._instances[validatorId];
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
module.exports = SuiMemoryObjectStorage;
|
package/lib/SuiObject.js
ADDED
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
const sui = require('@mysten/sui.js');
|
|
2
|
+
const SuiCommonMethods = require('./SuiCommonMethods.js');
|
|
3
|
+
|
|
4
|
+
class SuiObject extends SuiCommonMethods {
|
|
5
|
+
constructor(params = {}) {
|
|
6
|
+
super(params);
|
|
7
|
+
|
|
8
|
+
this._suiMaster = params.suiMaster;
|
|
9
|
+
if (!this._suiMaster) {
|
|
10
|
+
throw new Error('suiMaster is requried for suiPackage');
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
this._id = params.id || null;
|
|
14
|
+
this._version = params.version || null;
|
|
15
|
+
this._type = params.type || null;
|
|
16
|
+
|
|
17
|
+
this._fields = {}; // on-chain fields on the object
|
|
18
|
+
//
|
|
19
|
+
|
|
20
|
+
this._display = {}; // https://examples.sui.io/basics/display.html
|
|
21
|
+
// https://docs.sui.io/devnet/build/sui-object-display
|
|
22
|
+
|
|
23
|
+
this._owner = null; // Going to store it in the same format as in rpc responses
|
|
24
|
+
|
|
25
|
+
this._localProperties = {}; // object to store some local data for you to help with your local calculations, no interaction with blockchain
|
|
26
|
+
|
|
27
|
+
// this._ownerAddress = null;
|
|
28
|
+
|
|
29
|
+
this._isDeleted = false;
|
|
30
|
+
|
|
31
|
+
if (params.objectChange) {
|
|
32
|
+
this.tryToFillDataFromObjectChange(params.objectChange);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
this._constructedAt = new Date(); // just a helpful data so we can sort later when trying to find most recent item in different modules
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
get constructedAt() {
|
|
39
|
+
return this._constructedAt;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
static idsEqual(id1, id2) {
|
|
43
|
+
return (sui.normalizeSuiAddress(id1) === sui.normalizeSuiAddress(id2));
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
get isDeleted() {
|
|
47
|
+
return this._isDeleted;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
get isShared() {
|
|
51
|
+
return (this._owner && this._owner.Shared);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
get isImmutable() {
|
|
55
|
+
return (this._owner && this._owner == 'Immutable');
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
isOwnedBy(addressOrSuiObject) {
|
|
59
|
+
let toId = addressOrSuiObject;
|
|
60
|
+
if (toId.id) {
|
|
61
|
+
toId = toId.id;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (this._owner && this._owner.AddressOwner && this._owner.AddressOwner == toId) {
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
markAsDeleted() {
|
|
72
|
+
this._isDeleted = true;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
get id() {
|
|
76
|
+
return this._id;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
get type() {
|
|
80
|
+
return this._type;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* In module type name, without package and module prefix
|
|
85
|
+
*/
|
|
86
|
+
get typeName() {
|
|
87
|
+
return this._type ? this._type.split('::').pop() : null;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
idEquals(toId) {
|
|
91
|
+
if (!toId) {
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const thisAddress = this.address;
|
|
96
|
+
if (thisAddress && thisAddress === sui.normalizeSuiAddress(toId)) {
|
|
97
|
+
return true;
|
|
98
|
+
}
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
get address() {
|
|
103
|
+
try {
|
|
104
|
+
return sui.normalizeSuiAddress(this._id);
|
|
105
|
+
} catch (e) {
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
get fields() {
|
|
111
|
+
return this._fields;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
get display() {
|
|
115
|
+
return this._display;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
get localProperties() {
|
|
119
|
+
return this._localProperties;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
async getDynamicFields() {
|
|
123
|
+
const result = await this._suiMaster._provider.getDynamicFields({
|
|
124
|
+
parentId: this.address, // normalized id
|
|
125
|
+
options: {
|
|
126
|
+
showType: true,
|
|
127
|
+
showContent: true,
|
|
128
|
+
showOwner: true,
|
|
129
|
+
showDisplay: true,
|
|
130
|
+
"showPreviousTransaction": true,
|
|
131
|
+
"showBcs": false,
|
|
132
|
+
"showStorageRebate": true
|
|
133
|
+
},
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
async fetchFields() {
|
|
138
|
+
const result = await this._suiMaster._provider.getObject({
|
|
139
|
+
id: this.address, // normalized id
|
|
140
|
+
options: {
|
|
141
|
+
showType: true,
|
|
142
|
+
showContent: true,
|
|
143
|
+
showOwner: true,
|
|
144
|
+
showDisplay: true,
|
|
145
|
+
"showPreviousTransaction": true,
|
|
146
|
+
"showBcs": false,
|
|
147
|
+
"showStorageRebate": true
|
|
148
|
+
},
|
|
149
|
+
});
|
|
150
|
+
if (result && result.data) {
|
|
151
|
+
this.tryToFillDataFromObjectChange(result.data);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Try to fill local object properties with values from ( showObjectChanges = true ) rpc response
|
|
157
|
+
* @param {Object} objectChange
|
|
158
|
+
*/
|
|
159
|
+
tryToFillDataFromObjectChange(objectChange) {
|
|
160
|
+
if (!objectChange.objectId && objectChange.data && objectChange.data.objectId) {
|
|
161
|
+
objectChange = objectChange.data;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
if (objectChange.type && objectChange.type == 'deleted') {
|
|
165
|
+
this.markAsDeleted();
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// basic fields. Available both in getObject and in results of .moveCall
|
|
169
|
+
if (objectChange.objectId) {
|
|
170
|
+
if (!this._id) {
|
|
171
|
+
this._id = objectChange.objectId;
|
|
172
|
+
} else if (!this.idEquals(objectChange.objectId)) {
|
|
173
|
+
throw new Error('Trying to fill from different object');
|
|
174
|
+
}
|
|
175
|
+
if (objectChange.type && !this._type) {
|
|
176
|
+
this._type = objectChange.type;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
if (objectChange.version) {
|
|
180
|
+
this._version = BigInt(objectChange.version);
|
|
181
|
+
}
|
|
182
|
+
if (objectChange.objectType) {
|
|
183
|
+
this._type = `${objectChange.objectType}`;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// extra fields. Possible to get them from separate call to getObject or multiGetObjects
|
|
187
|
+
// .content
|
|
188
|
+
if (objectChange?.content?.fields) {
|
|
189
|
+
for (const key in objectChange?.content?.fields) {
|
|
190
|
+
if (key !== 'id') {
|
|
191
|
+
this._fields[key] = objectChange.content.fields[key];
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// .display
|
|
197
|
+
if (objectChange?.display?.data) {
|
|
198
|
+
for (const key in objectChange?.display?.data) {
|
|
199
|
+
this._display[key] = objectChange.display.data[key];
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// .owner
|
|
204
|
+
if (objectChange.owner) {
|
|
205
|
+
this._owner = objectChange.owner;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
}
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
module.exports = SuiObject;
|