suidouble 0.0.38 → 0.0.39
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/README.md +57 -7
- package/lib/SuiCoin.js +257 -0
- package/lib/SuiCoins.js +132 -0
- package/lib/SuiMaster.js +23 -16
- package/lib/SuiPackageModule.js +14 -8
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,10 +8,12 @@ Set of provider, package and object classes for javascript representation of Sui
|
|
|
8
8
|
- [Attaching a package](#attaching-a-package)
|
|
9
9
|
- [Interacting with smart contract](#interacting-with-smart-contract)
|
|
10
10
|
- [SuiObject](#suiobject)
|
|
11
|
+
- [Fetching objects](#fetching-objects)
|
|
11
12
|
- [Fetching Events](#fetching-events)
|
|
12
13
|
- [Subscribe to Events](#subscribing-to-events)
|
|
13
14
|
- [Executing smart contract method](#executing-smart-contract-method)
|
|
14
|
-
- [
|
|
15
|
+
- [Sending sui / coins with smart contract methods](#sending-sui--coins-with-smart-contract-methods)
|
|
16
|
+
- [Composing transaction block yourself](#composing-transaction-block-yourself)
|
|
15
17
|
- [Publishing the package](#publishing-the-package)
|
|
16
18
|
- [Upgrading the package](#upgrading-the-package)
|
|
17
19
|
- [Writing Sue Move intergration tests](#sui-move-integration-testing)
|
|
@@ -205,15 +207,65 @@ const res = await contract.moveCall('chat', 'post', ['0x10cded4f9df05e37b44e3be2
|
|
|
205
207
|
}
|
|
206
208
|
```
|
|
207
209
|
|
|
208
|
-
|
|
210
|
+
##### sending sui / coins with smart contract methods
|
|
211
|
+
|
|
212
|
+
If you need to transfer some SUI/coins as part of executing contract method, you can use a magic parameter in form of:
|
|
213
|
+
|
|
214
|
+
```javascript
|
|
215
|
+
{type: 'SUI', amount: 400000000000n}
|
|
216
|
+
// 400000000000 MISTs, if amount is BigInt, it's used in decimal items
|
|
217
|
+
{type: 'SUI', amount: '0.2'}
|
|
218
|
+
// 0.2 SUI , if amount is String, it's translated to decimals, using coin metadata in a lazy way
|
|
219
|
+
{type: '0x5d4b302506645c37ff133b98c4b50a5ae14841659738d6d733d59d0d217a93bf::coin::COIN', amount: '1'}
|
|
220
|
+
// 1 USDC
|
|
221
|
+
{type: '0xc060006111016b8a020ad5b33834984a437aaa7d3c74c18e09a95d48aceab08c::coin::COIN', amount: '99.99'}
|
|
222
|
+
// 99.99 USDT
|
|
223
|
+
```
|
|
209
224
|
|
|
210
|
-
|
|
225
|
+
So executing
|
|
211
226
|
|
|
212
227
|
```javascript
|
|
213
|
-
const
|
|
228
|
+
const params = [
|
|
229
|
+
chatShopObjectId,
|
|
230
|
+
{type: '0xc060006111016b8a020ad5b33834984a437aaa7d3c74c18e09a95d48aceab08c::coin::COIN', amount: '9.99'},
|
|
231
|
+
messageText,
|
|
232
|
+
];
|
|
233
|
+
const moveCallResult = await contract.moveCall('suidouble_chat', 'post_pay', params);
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
will send 9.99 USDT as the second parameter of the package method. Suidouble will convert needed coins using Sui's SplitCoins and MergeCoins internally to match amount you expect to send.
|
|
237
|
+
|
|
238
|
+
Some smart contracts requires clients to send coins in form of vectors. This is covered too, just pass magic parameter if the form of an array with one element:
|
|
239
|
+
|
|
240
|
+
```javascript
|
|
241
|
+
const params = [
|
|
242
|
+
chatShopObjectId,
|
|
243
|
+
[{type: '0xc060006111016b8a020ad5b33834984a437aaa7d3c74c18e09a95d48aceab08c::coin::COIN', amount: '9.99'}],
|
|
244
|
+
messageText,
|
|
245
|
+
];
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
Don't forget to test transactions sending real money on devnet/testnet first!
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
##### composing transaction block yourself
|
|
252
|
+
|
|
253
|
+
If you need more flexebility, there's always an option to construct the transaction block yourself:
|
|
254
|
+
|
|
255
|
+
```javascript
|
|
256
|
+
const { TransactionBlock, Transactions } = require('suidobule'); // this exposes classes from the "@mysten/sui.js", so you don't have to import them separately
|
|
257
|
+
|
|
258
|
+
const txb = new TransactionBlock();
|
|
259
|
+
txb.moveCall({
|
|
260
|
+
target: `package_id::module_id::method_name`,
|
|
261
|
+
arguments: [
|
|
262
|
+
txb.pure(something),
|
|
263
|
+
txb.object(someid),
|
|
264
|
+
],
|
|
265
|
+
});
|
|
266
|
+
const moveCallResult = await contract.moveCall('suidouble_chat', 'post_pay', {tx: txb});
|
|
214
267
|
```
|
|
215
268
|
|
|
216
|
-
@todo: sending other Coins
|
|
217
269
|
|
|
218
270
|
##### fetching objects
|
|
219
271
|
|
|
@@ -369,8 +421,6 @@ Take a look at [unit tests](test) code for some inspiration.
|
|
|
369
421
|
|
|
370
422
|
### Todo
|
|
371
423
|
|
|
372
|
-
- subscribe to events
|
|
373
|
-
- sending other coins as contract methods execution
|
|
374
424
|
- suiobject invalidation/fetching optimization
|
|
375
425
|
- better documentation
|
|
376
426
|
- unit tests coverage to 90%+
|
package/lib/SuiCoin.js
ADDED
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
const { Transactions } = require('@mysten/sui.js/transactions');
|
|
2
|
+
|
|
3
|
+
const safeList = {
|
|
4
|
+
'sui:mainnet': {
|
|
5
|
+
'0xa198f3be41cda8c07b3bf3fee02263526e535d682499806979a111e88a5a8d0f::coin::COIN': 'CELO',
|
|
6
|
+
'0x027792d9fed7f9844eb4839566001bb6f6cb4804f66aa2da6fe1ee242d896881::coin::COIN': 'tBTC',
|
|
7
|
+
'0x5d4b302506645c37ff133b98c4b50a5ae14841659738d6d733d59d0d217a93bf::coin::COIN': 'USDCeth',
|
|
8
|
+
'0xe32d3ebafa42e6011b87ef1087bbc6053b499bf6f095807b9013aff5a6ecd7bb::coin::COIN': 'USDCarb',
|
|
9
|
+
'0x909cba62ce96d54de25bec9502de5ca7b4f28901747bbf96b76c2e63ec5f1cba::coin::COIN': 'USDCbnb',
|
|
10
|
+
'0xcf72ec52c0f8ddead746252481fb44ff6e8485a39b803825bde6b00d77cdb0bb::coin::COIN': 'USDCpol',
|
|
11
|
+
'0xb231fcda8bbddb31f2ef02e6161444aec64a514e2c89279584ac9806ce9cf037::coin::COIN': 'USDCsol',
|
|
12
|
+
'0xc060006111016b8a020ad5b33834984a437aaa7d3c74c18e09a95d48aceab08c::coin::COIN': 'USDT',
|
|
13
|
+
'0x1e8b532cca6569cab9f9b9ebc73f8c13885012ade714729aa3b450e0339ac766::coin::COIN': 'WAVAX',
|
|
14
|
+
'0xb848cce11ef3a8f62eccea6eb5b35a12c4c2b1ee1af7755d02d7bd6218e8226f::coin::COIN': 'WBNB',
|
|
15
|
+
'0x027792d9fed7f9844eb4839566001bb6f6cb4804f66aa2da6fe1ee242d896881::coin::COIN': 'WBTC',
|
|
16
|
+
'0xaf8cd5edc19c4512f4259f0bee101a40d41ebed738ade5874359610ef8eeced5::coin::COIN': 'WETH',
|
|
17
|
+
'0x6081300950a4f1e2081580e919c210436a1bed49080502834950d31ee55a2396::coin::COIN': 'WFTM',
|
|
18
|
+
'0x66f87084e49c38f76502d17f87d17f943f183bb94117561eb573e075fdc5ff75::coin::COIN': 'WGLMR',
|
|
19
|
+
'0xdbe380b13a6d0f5cdedd58de8f04625263f113b3f9db32b3e1983f49e2841676::coin::COIN': 'WMATIC',
|
|
20
|
+
'0xb7844e289a8410e50fb3ca48d69eb9cf29e27d223ef90353fe1bd8e27ff8f3f8::coin::COIN': 'WSOL',
|
|
21
|
+
'0x2::sui::SUI': 'SUI',
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
class SuiCoin {
|
|
26
|
+
constructor(params = {}) {
|
|
27
|
+
this._coinType = params.coinType;
|
|
28
|
+
this._suiCoins = params.suiCoins;
|
|
29
|
+
|
|
30
|
+
this._exists = null;
|
|
31
|
+
this._metadata = null;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Normalize amount based on .decimals. Pass a string with a dot ('5.22', '0.0005') to convert it to units
|
|
36
|
+
* always use a dot, event for '1.0' or '100.0'.
|
|
37
|
+
* @param {String|Number|BigInt} amount
|
|
38
|
+
* @returns {BigInt}
|
|
39
|
+
*/
|
|
40
|
+
normalizeAmount(amount) {
|
|
41
|
+
if (typeof(amount) == 'string' && amount.indexOf('.') !== -1) {
|
|
42
|
+
if (!this.decimals) {
|
|
43
|
+
throw new Error('Please load coin metadata first');
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return BigInt(Math.floor(parseFloat(amount, 10) * Math.pow(10, this.decimals)));
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return BigInt(amount);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Normalize amount based on .decimals. Pass a string with a dot ('5.22', '0.0005') to convert it to units. No worries about loading metadata first.
|
|
54
|
+
* @param {String|Number|BigInt} amount
|
|
55
|
+
* @returns {BigInt}
|
|
56
|
+
*/
|
|
57
|
+
async lazyNormalizeAmount(amount) {
|
|
58
|
+
await this.getMetadata();
|
|
59
|
+
return this.normalizeAmount(amount);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
amountToString(amount) {
|
|
63
|
+
if (!this.decimals) {
|
|
64
|
+
throw new Error('Please load coin metadata first');
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const str = (''+BigInt(amount)).padStart(this.decimals + 1,'0');
|
|
68
|
+
const ind = str.length - this.decimals;
|
|
69
|
+
return str.substring(0, ind) + '.' + str.substring(ind);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
get suiMaster() {
|
|
73
|
+
return this._suiCoins.suiMaster;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
static safeList(connectedChain) {
|
|
77
|
+
return safeList[connectedChain];
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
get coinType() {
|
|
81
|
+
if (this._coinType.indexOf('0x') === 0) {
|
|
82
|
+
return this._coinType;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return '0x'+this._coinType;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
get decimals() {
|
|
89
|
+
if (this.metadata) {
|
|
90
|
+
return this.metadata.decimals;
|
|
91
|
+
}
|
|
92
|
+
return undefined;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
get metadata() {
|
|
96
|
+
return this._metadata;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
get safeList() {
|
|
100
|
+
if (this.suiMaster && this.suiMaster.connectedChain) {
|
|
101
|
+
if (safeList[this.suiMaster.connectedChain]) {
|
|
102
|
+
return safeList[this.suiMaster.connectedChain];
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return {};
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
get isSafe() {
|
|
110
|
+
if (this.safeList[this.coinType]) {
|
|
111
|
+
return true;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
get symbol() {
|
|
118
|
+
if (this.safeList[this.coinType]) {
|
|
119
|
+
return this.safeList[this.coinType];
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (this.metadata) {
|
|
123
|
+
return this.metadata.symbol;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
get name() {
|
|
130
|
+
return this.metadata.name;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
isSUI() {
|
|
134
|
+
return this._coinType.toLowerCase().indexOf('sui') > -1;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
async getMetadata() {
|
|
138
|
+
if (this._metadata) {
|
|
139
|
+
return this._metadata;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
let result = null;
|
|
143
|
+
try {
|
|
144
|
+
result = await this.suiMaster.provider.getCoinMetadata({
|
|
145
|
+
coinType: this.coinType,
|
|
146
|
+
});
|
|
147
|
+
} catch (e) {
|
|
148
|
+
console.error(e);
|
|
149
|
+
result = null;
|
|
150
|
+
}
|
|
151
|
+
if (!result) {
|
|
152
|
+
this._exists = false;
|
|
153
|
+
} else {
|
|
154
|
+
this._metadata = result;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return this._metadata;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
async getBalance(owner) {
|
|
161
|
+
const coins = [];
|
|
162
|
+
let result = null;
|
|
163
|
+
let cursor = null;
|
|
164
|
+
do {
|
|
165
|
+
result = await this.suiMaster.provider.getCoins({
|
|
166
|
+
owner: owner,
|
|
167
|
+
coinType: this.coinType,
|
|
168
|
+
limit: 50,
|
|
169
|
+
cursor: cursor,
|
|
170
|
+
});
|
|
171
|
+
coins.push(...result.data);
|
|
172
|
+
|
|
173
|
+
cursor = result.nextCursor;
|
|
174
|
+
} while (result.hasNextPage);
|
|
175
|
+
|
|
176
|
+
let totalAmount = BigInt(0);
|
|
177
|
+
for (const coin of coins) {
|
|
178
|
+
totalAmount = totalAmount + BigInt(coin.balance);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
return totalAmount;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
async coinOfAmountToTxCoin(txb, owner, amount, addEmptyCoins = false) {
|
|
185
|
+
const expectedAmountAsBigInt = BigInt(amount);
|
|
186
|
+
const coinIds = await this.coinObjectsEnoughForAmount(owner, expectedAmountAsBigInt, addEmptyCoins);
|
|
187
|
+
|
|
188
|
+
if (!coinIds || !coinIds.length) {
|
|
189
|
+
throw new Error('you do not have enough coins of type '+this.coinType);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (coinIds.length == 1) {
|
|
193
|
+
// only one coin object enough to cover the expense
|
|
194
|
+
if (this.isSUI()) {
|
|
195
|
+
const coinInput = txb.add(Transactions.SplitCoins(txb.gas, [txb.pure(expectedAmountAsBigInt)]));
|
|
196
|
+
return coinInput;
|
|
197
|
+
} else {
|
|
198
|
+
// some other coin
|
|
199
|
+
const coinInput = txb.add(Transactions.SplitCoins(txb.object(coinIds[0]), [txb.pure(expectedAmountAsBigInt)]));
|
|
200
|
+
return coinInput;
|
|
201
|
+
}
|
|
202
|
+
} else {
|
|
203
|
+
// few coin objects to merge
|
|
204
|
+
const coinIdToMergeIn = coinIds.shift();
|
|
205
|
+
txb.add(Transactions.MergeCoins(txb.object(coinIdToMergeIn), coinIds.map((id)=>{return txb.object(id);})));
|
|
206
|
+
const coinInputSplet = txb.add(Transactions.SplitCoins(txb.object(coinIdToMergeIn), [txb.pure(expectedAmountAsBigInt)]));
|
|
207
|
+
|
|
208
|
+
return coinInputSplet;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
async coinObjectsEnoughForAmount(owner, expectedAmount, addEmptyCoins = false) {
|
|
213
|
+
const expectedAmountAsBigInt = BigInt(expectedAmount);
|
|
214
|
+
|
|
215
|
+
const coinIds = [];
|
|
216
|
+
const coins = [];
|
|
217
|
+
|
|
218
|
+
let result = null;
|
|
219
|
+
let cursor = null;
|
|
220
|
+
do {
|
|
221
|
+
result = await this.suiMaster.provider.getCoins({
|
|
222
|
+
owner: owner,
|
|
223
|
+
coinType: this.coinType,
|
|
224
|
+
limit: 50,
|
|
225
|
+
cursor: cursor,
|
|
226
|
+
});
|
|
227
|
+
coins.push(...result.data);
|
|
228
|
+
|
|
229
|
+
cursor = result.nextCursor;
|
|
230
|
+
} while (result.hasNextPage);
|
|
231
|
+
|
|
232
|
+
coins.sort((a, b) => {
|
|
233
|
+
// From big to small
|
|
234
|
+
return Number(b.balance) - Number(a.balance);
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
let totalAmount = BigInt(0);
|
|
238
|
+
for (const coin of coins) {
|
|
239
|
+
if (totalAmount <= expectedAmountAsBigInt) {
|
|
240
|
+
coinIds.push(coin.coinObjectId);
|
|
241
|
+
totalAmount = totalAmount + BigInt(coin.balance);// totalAmount.add(coin.balance);
|
|
242
|
+
} else {
|
|
243
|
+
if (addEmptyCoins && BigInt(coin.balance) == 0n) {
|
|
244
|
+
coinIds.push(coin.coinObjectId);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
if (totalAmount >= expectedAmountAsBigInt) {
|
|
250
|
+
return coinIds;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
return null;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
module.exports = SuiCoin;
|
package/lib/SuiCoins.js
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
const SuiCoin = require('./SuiCoin.js');
|
|
2
|
+
const SuiCommonMethods = require('./SuiCommonMethods.js');
|
|
3
|
+
|
|
4
|
+
class SuiCoins extends SuiCommonMethods {
|
|
5
|
+
constructor(params = {}) {
|
|
6
|
+
super(params);
|
|
7
|
+
|
|
8
|
+
this._suiMaster = params.suiMaster;
|
|
9
|
+
if (!this._suiMaster) {
|
|
10
|
+
throw new Error('suiMaster is required');
|
|
11
|
+
}
|
|
12
|
+
this._coins = {};
|
|
13
|
+
|
|
14
|
+
this._isInitialized = false;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
get suiMaster() {
|
|
18
|
+
return this._suiMaster;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
get coins() {
|
|
22
|
+
return this._coins;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Optional common initialized to get a list and metadata of all safe coins defined in SuiCoin.js
|
|
27
|
+
*/
|
|
28
|
+
async init() {
|
|
29
|
+
if (this._isInitialized) {
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const safeList = SuiCoin.safeList(this._suiMaster.connectedChain);
|
|
34
|
+
const metadataPromises = [];
|
|
35
|
+
for (const coinType in safeList) {
|
|
36
|
+
const normalizedCoinType = this.normalizeCoinType(coinType);
|
|
37
|
+
if (!this._coins[normalizedCoinType]) {
|
|
38
|
+
const suiCoin = new SuiCoin({
|
|
39
|
+
coinType: normalizedCoinType,
|
|
40
|
+
suiCoins: this,
|
|
41
|
+
});
|
|
42
|
+
console.log('adding coin with type', normalizedCoinType);
|
|
43
|
+
this._coins[normalizedCoinType] = suiCoin;
|
|
44
|
+
|
|
45
|
+
const metadataPromise = new Promise(async(res)=>{
|
|
46
|
+
try {
|
|
47
|
+
await suiCoin.getMetadata();
|
|
48
|
+
} catch (e) {
|
|
49
|
+
console.error(e);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
res();
|
|
53
|
+
});
|
|
54
|
+
metadataPromises.push(metadataPromise);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
await Promise.all(metadataPromises);
|
|
59
|
+
|
|
60
|
+
this._isInitialized = true;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
normalizeCoinType(coinType) {
|
|
64
|
+
if (coinType.indexOf('::') == -1) {
|
|
65
|
+
if (coinType.toLowerCase() == 'sui') {
|
|
66
|
+
return '0x2::sui::SUI';
|
|
67
|
+
} else {
|
|
68
|
+
for (const key in this._coins) {
|
|
69
|
+
if (key == coinType) {
|
|
70
|
+
return this._coins[key].coinType;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const safeList = SuiCoin.safeList(this._suiMaster.connectedChain);
|
|
75
|
+
for (const key in safeList) {
|
|
76
|
+
if (safeList[key] == coinType) {
|
|
77
|
+
return key;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (coinType.indexOf('0x') == -1) {
|
|
83
|
+
return '0x'+coinType+'::coin::COIN';
|
|
84
|
+
} else {
|
|
85
|
+
return ''+coinType+'::coin::COIN';
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (coinType.indexOf('0x') == -1) {
|
|
90
|
+
coinType = '0x'+coinType;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (coinType == '0x0000000000000000000000000000000000000000000000000000000000000002::sui::SUI') {
|
|
94
|
+
return '0x2::sui::SUI';
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return coinType;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
get(coinType) {
|
|
101
|
+
const normalizedCoinType = this.normalizeCoinType(coinType);
|
|
102
|
+
let suiCoin = this._coins[normalizedCoinType];
|
|
103
|
+
if (suiCoin) {
|
|
104
|
+
return suiCoin;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
suiCoin = new SuiCoin({
|
|
108
|
+
coinType: normalizedCoinType,
|
|
109
|
+
suiCoins: this,
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
this._coins[normalizedCoinType] = suiCoin;
|
|
113
|
+
|
|
114
|
+
return suiCoin;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
static _singleInstances = {};
|
|
118
|
+
static getSingleton(params = {}) {
|
|
119
|
+
const suiMaster = params.suiMaster;
|
|
120
|
+
const connectedChain = suiMaster.connectedChain;
|
|
121
|
+
|
|
122
|
+
if (SuiCoins._singleInstances[connectedChain]) {
|
|
123
|
+
return SuiCoins._singleInstances[connectedChain];
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
SuiCoins._singleInstances[connectedChain] = new SuiCoins(params);
|
|
127
|
+
return SuiCoins._singleInstances[connectedChain];
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
module.exports = SuiCoins;
|
package/lib/SuiMaster.js
CHANGED
|
@@ -7,6 +7,7 @@ const SuiPaginatedResponse = require('./SuiPaginatedResponse.js');
|
|
|
7
7
|
const SuiObject = require('./SuiObject.js');
|
|
8
8
|
const SuiTransaction = require('./SuiTransaction.js');
|
|
9
9
|
const SuiEvent = require('./SuiEvent.js');
|
|
10
|
+
const SuiCoins = require('./SuiCoins.js');
|
|
10
11
|
|
|
11
12
|
class SuiMaster extends SuiCommonMethods {
|
|
12
13
|
constructor(params = {}) {
|
|
@@ -103,6 +104,15 @@ class SuiMaster extends SuiCommonMethods {
|
|
|
103
104
|
this._initialized = false;
|
|
104
105
|
|
|
105
106
|
this._packages = {};
|
|
107
|
+
|
|
108
|
+
this._suiCoins = new SuiCoins({
|
|
109
|
+
suiMaster: this,
|
|
110
|
+
debug: this._debug,
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
get suiCoins() {
|
|
115
|
+
return this._suiCoins;
|
|
106
116
|
}
|
|
107
117
|
|
|
108
118
|
get MIST_PER_SUI() {
|
|
@@ -237,26 +247,23 @@ class SuiMaster extends SuiCommonMethods {
|
|
|
237
247
|
return amount;
|
|
238
248
|
}
|
|
239
249
|
|
|
240
|
-
|
|
250
|
+
/**
|
|
251
|
+
* Query the balance of specific coinType for an owner. If owner == null, returns balance of connected address owner
|
|
252
|
+
*
|
|
253
|
+
* @param {String} coinType
|
|
254
|
+
* @param {String|null} owner
|
|
255
|
+
* @returns BigInt
|
|
256
|
+
*/
|
|
257
|
+
async getBalance(coinType = '0x2::sui::SUI', owner = null) {
|
|
241
258
|
await this.initialize();
|
|
242
259
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
try {
|
|
247
|
-
res = await this._provider.getBalance({owner: this._address, coinType});
|
|
248
|
-
} catch (e) {
|
|
249
|
-
this.log('error', e);
|
|
250
|
-
res = null;
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
let ret = BigInt(0);
|
|
254
|
-
if (res && res.totalBalance) {
|
|
255
|
-
ret = BigInt(res.totalBalance);
|
|
260
|
+
let queryingBalanceOf = owner;
|
|
261
|
+
if (!queryingBalanceOf && this.address) {
|
|
262
|
+
queryingBalanceOf = this.address;
|
|
256
263
|
}
|
|
257
264
|
|
|
258
|
-
this.
|
|
259
|
-
return
|
|
265
|
+
const suiCoin = this._suiCoins.get(coinType);
|
|
266
|
+
return await (suiCoin.getBalance(queryingBalanceOf));
|
|
260
267
|
}
|
|
261
268
|
|
|
262
269
|
// export type TransactionFilter =
|
package/lib/SuiPackageModule.js
CHANGED
|
@@ -124,15 +124,21 @@ class SuiPackageModule extends SuiCommonMethods {
|
|
|
124
124
|
const callArgs = [];
|
|
125
125
|
|
|
126
126
|
for (let param of params) {
|
|
127
|
-
if (param && param.type && param.amount
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
127
|
+
if (param && param.type && param.amount) {
|
|
128
|
+
const ownerAddress = this._suiMaster.address;
|
|
129
|
+
|
|
130
|
+
const suiCoin = await this._suiMaster.suiCoins.get(param.type);
|
|
131
|
+
const txCoinToSend = await suiCoin.coinOfAmountToTxCoin(tx, ownerAddress, param.amount);
|
|
132
|
+
|
|
133
|
+
callArgs.push(txCoinToSend);
|
|
134
|
+
} else if (param && Array.isArray(param) && param.length == 1 && param[0].type && param[0].amount) {
|
|
132
135
|
// vector<Coin<SUI>>
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
+
const ownerAddress = this._suiMaster.address;
|
|
137
|
+
|
|
138
|
+
const suiCoin = await this._suiMaster.suiCoins.get(param.type);
|
|
139
|
+
const txCoinToSend = await suiCoin.coinOfAmountToTxCoin(tx, ownerAddress, param.amount);
|
|
140
|
+
|
|
141
|
+
callArgs.push(tx.makeMoveVec({ objects: [txCoinToSend]}));
|
|
136
142
|
} else {
|
|
137
143
|
callArgs.push(tx.pure(param));
|
|
138
144
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "suidouble",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.39",
|
|
4
4
|
"description": "Set of provider, package and object classes for javascript representation of Sui Move smart contracts. Use same code for publishing, upgrading, integration testing, interaction with smart contracts and integration in browser web3 dapps",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|