suidouble 1.14.2 → 1.14.3-1

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/index.js CHANGED
@@ -4,7 +4,10 @@ import SuiTestScenario from './lib/SuiTestScenario.js';
4
4
  import SuiObject from './lib/SuiObject.js';
5
5
  import SuiUtils from './lib/SuiUtils.js';
6
6
  import SuiLocalTestValidator from './lib/SuiLocalTestValidator.js';
7
- import { Transaction, Commands } from '@mysten/sui/transactions';
7
+ import SuiMemoryObjectStorage from './lib/SuiMemoryObjectStorage.js';
8
+ import SuiCoin from './lib/SuiCoin.js';
9
+ import SuiCoins from './lib/SuiCoins.js';
10
+ import { Transaction, Commands } from '@mysten/sui/transactions';
8
11
  import { bcs } from '@mysten/sui/bcs';
9
12
 
10
13
  const txInput = SuiUtils.txInput;
@@ -22,4 +25,7 @@ export {
22
25
  SuiUtils,
23
26
  txInput,
24
27
  bcs,
28
+ SuiMemoryObjectStorage,
29
+ SuiCoin,
30
+ SuiCoins,
25
31
  };
package/lib/SuiCoin.js CHANGED
@@ -13,9 +13,18 @@ import { Commands, Transaction } from '@mysten/sui/transactions';
13
13
  * @property {string} symbol - Symbol for the token
14
14
  * @property {string} [id] - Meta id
15
15
  * @property {string} [type] - Coin type string
16
+ *
17
+ *
18
+ * @typedef SuidoubleCoinBalance
19
+ * @type {object}
20
+ * @property {SuiCoin} coin
21
+ * @property {string} coinType
22
+ * @property {number} coinObjectCount
23
+ * @property {bigint} totalBalance
24
+ * @property {Object.<string,string>} lockedBalance
25
+ *
16
26
  */
17
27
 
18
-
19
28
  /** Coin metadata object */
20
29
  export default class SuiCoin {
21
30
 
@@ -53,38 +62,94 @@ export default class SuiCoin {
53
62
 
54
63
  /**
55
64
  * 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.
56
- * @param {String|Number|BigInt} amount
57
- * @returns {BigInt}
65
+ * @param {String|Number|bigint} amount
66
+ * @returns {Promise.<bigint>}
58
67
  */
59
68
  async lazyNormalizeAmount(amount) {
60
69
  await this.getMetadata();
61
70
  return this.normalizeAmount(amount);
62
71
  }
63
72
 
64
- amountToString(amount) {
73
+ /**
74
+ * Get readable representation of amount value (system one, bigint or converted from bigint, NOT the '1.99' etc)
75
+ * based on coin decimals metadata ( so it expects metadata to be loaded or set).
76
+ *
77
+ * @param {Object} params - format parameters
78
+ * @param {boolean} params.withAbbr - append K, M, B, T for large amounts. Suiet-style
79
+ * @param {boolean|string} params.separateThousands - separate thousands, by ',' or by specific delimeter
80
+ *
81
+ * @returns {string}
82
+ */
83
+ amountToString(amount, options = {}) {
65
84
  if (!this.decimals) {
66
85
  throw new Error('Please load coin metadata first');
67
86
  }
68
87
 
88
+ const withAbbr = !!options.withAbbr;
89
+ const separateThousands = options.separateThousands;
90
+
69
91
  const str = (''+BigInt(amount)).padStart(this.decimals + 1,'0');
70
92
  const ind = str.length - this.decimals;
71
93
  let asFloatString = str.substring(0, ind) + '.' + str.substring(ind);
72
94
 
73
- /// yep, I can't find a better way to strip extra 0 at the end. All regexes are not ok. Ping me if you have a good one
74
- let i = asFloatString.length - 1;
75
- let haveNotMetNoZero = false;
76
- while (i > 0 && !haveNotMetNoZero) {
77
- if (asFloatString.substring(i, i+1) === '0' && asFloatString.substring(i-1, i) !== '.') {
78
- asFloatString = asFloatString.substring(0, i);
79
- } else {
80
- haveNotMetNoZero = true;
95
+ if (asFloatString.includes('.')) {
96
+ asFloatString = asFloatString.replace(/(\.\d*?)0+$/, '$1').replace(/\.$/, '');
97
+ if (!asFloatString.includes('.')) {
98
+ asFloatString = '' + asFloatString + '.0';
99
+ }
100
+ }
101
+
102
+ if (withAbbr) {
103
+ const asBig = BigInt(Math.floor(Number(asFloatString)));
104
+
105
+ if (asBig > 1000n) {
106
+ if (asBig < 1000000n) return this.formatWithAbbr(asBig, 1000n, 'K', separateThousands);
107
+ if (asBig >= 1000000n && asBig < 1000000000n) return this.formatWithAbbr(asBig, 1000000n, 'M', separateThousands);
108
+ if (asBig >= 1000000000n && asBig < 1000000000000n) return this.formatWithAbbr(asBig, 1000000000n, 'B', separateThousands);
109
+ if (asBig >= 1000000000000n) return this.formatWithAbbr(asBig, 1000000000000n, 'T', separateThousands);
81
110
  }
82
- i--;
111
+ }
112
+
113
+ if (separateThousands) {
114
+ // asFloatString has '.' anyway ( see above )
115
+ const [integerPart, decimalPart] = asFloatString.split('.'); // Split into integer and decimal parts
116
+ const separator = (typeof separateThousands === 'string') ? separateThousands : ',';
117
+ const formattedInteger = integerPart.replace(/\B(?=(\d{3})+(?!\d))/g, separator);
118
+ asFloatString = '' + formattedInteger + '.' + decimalPart;
83
119
  }
84
120
 
85
121
  return asFloatString;
86
122
  }
87
123
 
124
+
125
+ /**
126
+ * Format large amounts
127
+ *
128
+ * thanks @bruceeewong and @suiet
129
+ *
130
+ * @param {bigint} amount
131
+ * @param {bigint} measureUnit
132
+ * @param {string} abbrSymbol
133
+ *
134
+ * @returns {string}
135
+ */
136
+ formatWithAbbr(amount, measureUnit, abbrSymbol, separateThousands = false) {
137
+ let showAmount = (''+Math.floor(Number(amount) / Number(measureUnit / 1000n)));
138
+ showAmount = showAmount.padEnd(4, '0');
139
+
140
+ const result = Intl.NumberFormat('en-US').format(Number(showAmount));
141
+
142
+ let separator = '';
143
+ if (separateThousands) {
144
+ separator = (typeof separateThousands === 'string') ? separateThousands : ',';
145
+ }
146
+
147
+ const pcs = result.split(',');
148
+ const lastPc = pcs.pop();
149
+ return pcs.join( separator ) + '.' + lastPc + abbrSymbol;
150
+ }
151
+
152
+
88
153
  get suiMaster() {
89
154
  return this._suiCoins.suiMaster;
90
155
  }
@@ -140,6 +205,7 @@ export default class SuiCoin {
140
205
  /**
141
206
  * set predefined coin metadata so it will not be fetched from RPC
142
207
  * @param {CoinMeta} meta
208
+ *
143
209
  * @returns {boolean} if processed ok
144
210
  */
145
211
  setMetadata(meta) {
@@ -152,11 +218,25 @@ export default class SuiCoin {
152
218
  return false;
153
219
  }
154
220
 
221
+ /**
222
+ * Load coin metadata from the blockchain. As a good pattern, it's better to have metadata hard-coded or cached
223
+ * and set via suiMaster.suiCoins.setCoinMetas(...)
224
+ *
225
+ * @returns {Promise.<boolean>}
226
+ */
155
227
  async getMetadata() {
156
228
  if (this._metadata) {
157
229
  return this._metadata;
158
230
  }
159
231
 
232
+ if (this.__getMetadataPromise) {
233
+ return await this.__getMetadataPromise();
234
+ }
235
+
236
+ // be sure it asyncs in 1 thread
237
+ this.__getMetadataResolver = null;
238
+ this.__getMetadataPromise = new Promise((res)=>{ this.__getMetadataResolver = res; });
239
+
160
240
  let result = null;
161
241
  try {
162
242
  result = await this.suiMaster.client.getCoinMetadata({
@@ -173,9 +253,17 @@ export default class SuiCoin {
173
253
  this._exists = true;
174
254
  }
175
255
 
176
- return this._metadata;
256
+ this.__getMetadataResolver(true);
257
+
258
+ return true;
177
259
  }
178
260
 
261
+ /**
262
+ * Get coin balance of the wallet
263
+ * @param {string} owner
264
+ *
265
+ * @returns {Promise.<bigint>}
266
+ */
179
267
  async getBalance(owner) {
180
268
  const coins = [];
181
269
  let result = null;
@@ -208,7 +296,8 @@ export default class SuiCoin {
208
296
  * @param {string} owner - address of the owner
209
297
  * @param {BigInt|string} amount - amount of coin. BigIng or String to be normalized via Coin decimals, "0.05" for 0.05 sui
210
298
  * @param {boolean} addEmptyCoins - attach coins == 0 to the list
211
- * @returns {TransactionObjectArgument}
299
+ *
300
+ * @returns {Promise.<TransactionObjectArgument>}
212
301
  */
213
302
  async coinOfAmountToTxCoin(txb, owner, amount, addEmptyCoins = false) {
214
303
  const normalizedAmount = await this.lazyNormalizeAmount(amount);
package/lib/SuiCoins.js CHANGED
@@ -5,6 +5,7 @@ import { normalizeStructTag } from "@mysten/sui/utils";
5
5
 
6
6
  /**
7
7
  * @typedef {import("./SuiCoin.js").CoinMeta} CoinMeta
8
+ * @typedef {import("./SuiCoin.js").SuidoubleCoinBalance} SuidoubleCoinBalance
8
9
  * @typedef {import("./SuiMaster.js").default} SuiMaster
9
10
  */
10
11
 
@@ -79,6 +80,42 @@ export default class SuiCoins extends SuiCommonMethods {
79
80
  return processedCount;
80
81
  }
81
82
 
83
+ /**
84
+ * Get all CoinBalance[] for the specific address or connected address
85
+ *
86
+ * @param {Object} params
87
+ * @param {string?} params.owner - owner address, if skipped - will query for connected wallet address
88
+ *
89
+ * @returns {Promise.<Array.<SuidoubleCoinBalance>>}
90
+ */
91
+ async getAllBalances(params = {}) {
92
+ let owner = params.owner;
93
+ if (!owner) {
94
+ owner = this._suiMaster.address;
95
+ }
96
+
97
+ /** @type {Array.<SuidoubleCoinBalance>} */
98
+ const ret = [];
99
+
100
+ const nativeCoinBalances = await this._suiMaster.client.getAllBalances({
101
+ owner,
102
+ });
103
+
104
+ for (const nativeCoinBalance of nativeCoinBalances) {
105
+ /** @type {SuidoubleCoinBalance} */
106
+ const coinBalance = {
107
+ coin: this.get(nativeCoinBalance.coinType),
108
+ coinType: nativeCoinBalance.coinType,
109
+ coinObjectCount: nativeCoinBalance.coinObjectCount,
110
+ totalBalance: BigInt(nativeCoinBalance.totalBalance),
111
+ lockedBalance: nativeCoinBalance.lockedBalance,
112
+ };
113
+ ret.push(coinBalance);
114
+ }
115
+
116
+ return ret;
117
+ }
118
+
82
119
  /**
83
120
  * normalize coinType string to sui's coin type. As extra, may take 'sui' or 'SUI' as the type and return type for it
84
121
  * @param {string} coinType
@@ -106,6 +143,7 @@ export default class SuiCoins extends SuiCommonMethods {
106
143
  * Return instance of SuiCoin of specific type
107
144
  *
108
145
  * @param {string} coinType - MoveType, or 'SUI' as helper
146
+ *
109
147
  * @returns {SuiCoin}
110
148
  */
111
149
  get(coinType) {
package/lib/SuiMaster.js CHANGED
@@ -102,6 +102,7 @@ export default class SuiMaster extends SuiCommonMethods {
102
102
  }
103
103
 
104
104
  // we are differient single instances of object storage by provider name (so we can separate like devnet-testnet entities if needed)
105
+ /** @type {SuiMemoryObjectStorage} */
105
106
  this._objectStorage = SuiMemoryObjectStorage.instanceOf(this._providerName, {
106
107
  debug: this._debug,
107
108
  suiMaster: this,
@@ -111,6 +112,7 @@ export default class SuiMaster extends SuiCommonMethods {
111
112
 
112
113
  this._packages = {};
113
114
 
115
+ /** @type {SuiCoins} */
114
116
  this._suiCoins = new SuiCoins({
115
117
  suiMaster: this,
116
118
  debug: this._debug,
@@ -161,6 +163,11 @@ export default class SuiMaster extends SuiCommonMethods {
161
163
  return SuiEvent;
162
164
  }
163
165
 
166
+ /**
167
+ * Storage storing all objects interacted by this suiMaster
168
+ *
169
+ * @type {SuiMemoryObjectStorage}
170
+ */
164
171
  get objectStorage() {
165
172
  return this._objectStorage;
166
173
  }
@@ -1,10 +1,29 @@
1
1
  import SuiCommonMethods from './SuiCommonMethods.js';
2
-
2
+ import SuiObject from './SuiObject.js';
3
+
4
+ /**
5
+ * Class to work with SuiObject's in bulk
6
+ *
7
+ * Sample usage:
8
+ * ```
9
+ * suiMemoryObjectStorage.push(id);
10
+ * suiMemoryObjectStorage.push(suiObject);
11
+ * await suiMemoryObjectStorage.fetchObjects();
12
+ * suiMemoryObjectStorage.byAddress(id);
13
+ * ```
14
+ */
3
15
  export default class SuiMemoryObjectStorage extends SuiCommonMethods {
16
+ /**
17
+ * SuiMemoryObjectStorage constructor
18
+ * @param {Object} params - Initialization parameters
19
+ * @param {SuiMaster} params.suiMaster - instance of SuiMaster
20
+ */
4
21
  constructor(params = {}) {
5
22
  super(params);
6
23
 
7
24
  this._suiMaster = params.suiMaster;
25
+
26
+ /** @type {Object.<string, SuiObject>} */
8
27
  this._objects = {};
9
28
  }
10
29
 
@@ -44,14 +63,29 @@ export default class SuiMemoryObjectStorage extends SuiCommonMethods {
44
63
  return mostRecentObject;
45
64
  }
46
65
 
47
- push(object) {
48
- if (object.address) {
49
- this._objects[object.address] = object;
66
+ /**
67
+ * @param {SuiObject | string} suiObjectOrId
68
+ *
69
+ * @returns {SuiObject | null}
70
+ */
71
+ push(suiObjectOrId) {
72
+ if (suiObjectOrId && suiObjectOrId.address) {
73
+ const /** @type {SuiObject} */ obj = suiObjectOrId;
74
+ this._objects[obj.address] = obj;
75
+
76
+ return obj;
77
+ } else if (suiObjectOrId && (''+suiObjectOrId).indexOf('0x') === 0) {
78
+ if (this._objects[suiObjectOrId]) {
79
+ return this._objects[suiObjectOrId];
80
+ }
50
81
 
51
- return true;
82
+ const obj = new SuiObject({id: suiObjectOrId, suiMaster: this._suiMaster});
83
+ this._objects[obj.address] = obj;
84
+
85
+ return obj;
52
86
  }
53
87
 
54
- return false;
88
+ return null;
55
89
  }
56
90
 
57
91
  byAddress(address) {
@@ -125,6 +159,13 @@ export default class SuiMemoryObjectStorage extends SuiCommonMethods {
125
159
 
126
160
  static _instances = {};
127
161
 
162
+ /**
163
+ * @param {string} validatorId - just a string for single instance identifier
164
+ * @param {Object} params - Initialization parameters
165
+ * @param {SuiMaster} params.suiMaster - instance of SuiMaster
166
+ *
167
+ * @returns {SuiMemoryObjectStorage}
168
+ */
128
169
  static instanceOf(validatorId, params = {}) {
129
170
  if (SuiMemoryObjectStorage._instances[validatorId]) {
130
171
  return SuiMemoryObjectStorage._instances[validatorId];
package/lib/SuiPackage.js CHANGED
@@ -501,7 +501,7 @@ export default class SuiPackage extends SuiObject {
501
501
  * @returns Boolean true on success
502
502
  */
503
503
  async build(params = {}) {
504
- this.log('builing a package...');
504
+ this.log('building a package...');
505
505
 
506
506
  const path = this._path;
507
507
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "suidouble",
3
- "version": "1.14.2",
3
+ "version": "1.14.3-1",
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
  "type": "module",
@@ -22,8 +22,8 @@
22
22
  "author": "suidouble (https://github.com/suidouble)",
23
23
  "license": "Apache-2.0",
24
24
  "dependencies": {
25
- "@mysten/sui": "^1.14.2",
26
- "@polymedia/coinmeta": "^0.0.16",
25
+ "@mysten/sui": "^1.14.3",
26
+ "@polymedia/coinmeta": "^0.0.17",
27
27
  "@wallet-standard/core": "^1.0.3",
28
28
  "websocket": "^1.0.35"
29
29
  },
@@ -5,6 +5,8 @@ import { SuiMaster, SuiLocalTestValidator, Transaction } from '../index.js';
5
5
  const { test } = t;
6
6
 
7
7
  let suiLocalTestValidator = null;
8
+
9
+ /** @type {SuiMaster} */
8
10
  let suiMaster = null;
9
11
 
10
12
  test('spawn local test node', async t => {
@@ -33,13 +35,6 @@ test('type is normalized for SUI', async t => {
33
35
  const suiCoin5 = suiMaster.suiCoins.get('2::sui::SUI');
34
36
  const suiCoin6 = suiMaster.suiCoins.get('0000000000000000000000000000000000000000000000000000000000000002::sui::SUI');
35
37
 
36
- console.log(suiCoin1.coinType);
37
- console.log(suiCoin2.coinType);
38
- console.log(suiCoin3.coinType);
39
- console.log(suiCoin4.coinType);
40
- console.log(suiCoin5.coinType);
41
- console.log(suiCoin6.coinType);
42
-
43
38
  t.ok(suiCoin1.coinType == suiCoin2.coinType);
44
39
  t.ok(suiCoin1.coinType == suiCoin3.coinType);
45
40
  t.ok(suiCoin1.coinType == suiCoin4.coinType);
@@ -67,6 +62,9 @@ test('string representation works ok', async t => {
67
62
  const toDisplay2 = suiCoin.amountToString(1); // 1 mist
68
63
  t.equal(toDisplay2, '0.000000001');
69
64
 
65
+ const toDisplay1000 = suiCoin.amountToString(1000); // 1000 mist
66
+ t.equal(toDisplay1000, '0.000001');
67
+
70
68
  const toDisplay3 = suiCoin.amountToString(suiMaster.MIST_PER_SUI * BigInt(1000) + BigInt(1)); // 1000 SUI + 1 mist
71
69
  t.equal(toDisplay3, '1000.000000001');
72
70
 
@@ -74,6 +72,111 @@ test('string representation works ok', async t => {
74
72
  t.equal(toDisplay4, '999.999999999');
75
73
  });
76
74
 
75
+
76
+ test('string representation (withAbbr) works ok', async t => {
77
+ const suiCoin = suiMaster.suiCoins.get('sui');
78
+ await suiCoin.getMetadata();
79
+
80
+ // it should dispaly the same on the low amounts:
81
+
82
+ const toDisplay1 = suiCoin.amountToString(suiMaster.MIST_PER_SUI, {withAbbr: true});
83
+ t.equal(toDisplay1, '1.0');
84
+
85
+ const toDisplay2 = suiCoin.amountToString(1, {withAbbr: true}); // 1 mist
86
+ t.equal(toDisplay2, '0.000000001');
87
+
88
+ const toDisplay1000 = suiCoin.amountToString(1000, {withAbbr: true}); // 1000 mist
89
+ t.equal(toDisplay1000, '0.000001');
90
+
91
+ const toDisplay3 = suiCoin.amountToString(suiMaster.MIST_PER_SUI * BigInt(1000) + BigInt(1), {withAbbr: true}); // 1000 SUI + 1 mist
92
+ t.equal(toDisplay3, '1000.000000001');
93
+
94
+ const toDisplay4 = suiCoin.amountToString(suiMaster.MIST_PER_SUI * BigInt(1000) - BigInt(1), {withAbbr: true}); // 1000 SUI - 1 mist
95
+ t.equal(toDisplay4, '999.999999999');
96
+
97
+ // things are getting interesting starting from '1001.0'
98
+
99
+ const toDisplayK1 = suiCoin.amountToString(suiMaster.MIST_PER_SUI * BigInt(1001) + BigInt(1), {withAbbr: true}); // 1000 SUI + 1 mist
100
+ t.equal(toDisplayK1, '1.001K');
101
+ const toDisplayK2 = suiCoin.amountToString(suiMaster.MIST_PER_SUI * BigInt(2000), {withAbbr: true});
102
+ t.equal(toDisplayK2, '2.000K');
103
+ const toDisplayK3 = suiCoin.amountToString(suiMaster.MIST_PER_SUI * BigInt(999900), {withAbbr: true});
104
+ t.equal(toDisplayK3, '999.900K');
105
+
106
+ const toDisplayM1 = suiCoin.amountToString(suiMaster.MIST_PER_SUI * BigInt(1000000) + BigInt(1), {withAbbr: true}); // 1000 SUI + 1 mist
107
+ t.equal(toDisplayM1, '1.000M');
108
+ const toDisplayM2 = suiCoin.amountToString(suiMaster.MIST_PER_SUI * BigInt(2000000) + BigInt(900), {withAbbr: true}); // 1000 SUI + 1 mist
109
+ t.equal(toDisplayM2, '2.000M');
110
+
111
+ const toDisplayM2spec = suiCoin.amountToString(148518424765531477n, {withAbbr: true}); // 1000 SUI + 1 mist
112
+ t.equal(toDisplayM2spec, '148.518M');
113
+
114
+
115
+ const toDisplayB1 = suiCoin.amountToString(suiMaster.MIST_PER_SUI * BigInt(1000000000) + BigInt(1), {withAbbr: true}); // 1000 SUI + 1 mist
116
+ t.equal(toDisplayB1, '1.000B');
117
+
118
+ const toDisplayB2spec = suiCoin.amountToString(148518424765531477000n, {withAbbr: true}); // 1000 SUI + 1 mist
119
+ t.equal(toDisplayB2spec, '148.518B');
120
+
121
+ const toDisplayT1 = suiCoin.amountToString(suiMaster.MIST_PER_SUI * BigInt(1000000000000) + BigInt(1), {withAbbr: true}); // 1000 SUI + 1 mist
122
+ t.equal(toDisplayT1, '1.000T');
123
+
124
+ const toDisplayT2spec = suiCoin.amountToString(148518424765531477000000n, {withAbbr: true}); // 1000 SUI + 1 mist
125
+ t.equal(toDisplayT2spec, '148.518T');
126
+
127
+ const toDisplayT20spec = suiCoin.amountToString(148518424765531477000000000n, {withAbbr: true}); // 1000 SUI + 1 mist
128
+ t.equal(toDisplayT20spec, '148518.424T');
129
+
130
+ const toDisplayT20spec2 = suiCoin.amountToString(148518424765531477000000000n, {withAbbr: true, separateThousands: true}); // 1000 SUI + 1 mist
131
+ t.equal(toDisplayT20spec2, '148,518.424T');
132
+ });
133
+
134
+
135
+ test('string representation (separateThousands) works ok', async t => {
136
+ const suiCoin = suiMaster.suiCoins.get('sui');
137
+ await suiCoin.getMetadata();
138
+
139
+ // it should dispaly the same on the low amounts:
140
+
141
+ const toDisplay1 = suiCoin.amountToString(suiMaster.MIST_PER_SUI, {separateThousands: true});
142
+ t.equal(toDisplay1, '1.0');
143
+
144
+ const toDisplay2 = suiCoin.amountToString(1, {separateThousands: true}); // 1 mist
145
+ t.equal(toDisplay2, '0.000000001');
146
+
147
+ const toDisplay1000 = suiCoin.amountToString(1000, {separateThousands: true}); // 1000 mist
148
+ t.equal(toDisplay1000, '0.000001');
149
+
150
+ const toDisplay3 = suiCoin.amountToString(suiMaster.MIST_PER_SUI * BigInt(1000) + BigInt(1), {separateThousands: true}); // 1000 SUI + 1 mist
151
+ t.equal(toDisplay3, '1,000.000000001');
152
+
153
+ const toDisplay4 = suiCoin.amountToString(suiMaster.MIST_PER_SUI * BigInt(1000) - BigInt(1), {separateThousands: true}); // 1000 SUI - 1 mist
154
+ t.equal(toDisplay4, '999.999999999');
155
+
156
+ // things are getting interesting starting from '1001.0'
157
+
158
+ const toDisplayK1 = suiCoin.amountToString(suiMaster.MIST_PER_SUI * BigInt(1001) + BigInt(1), {separateThousands: true});
159
+ t.equal(toDisplayK1, '1,001.000000001');
160
+ const toDisplayK2 = suiCoin.amountToString(suiMaster.MIST_PER_SUI * BigInt(2000), {separateThousands: true});
161
+ t.equal(toDisplayK2, '2,000.0');
162
+ const toDisplayK3 = suiCoin.amountToString(suiMaster.MIST_PER_SUI * BigInt(999900), {separateThousands: true});
163
+ t.equal(toDisplayK3, '999,900.0');
164
+
165
+ const toDisplayM1 = suiCoin.amountToString(suiMaster.MIST_PER_SUI * BigInt(1000000) + BigInt(1), {separateThousands: true});
166
+ t.equal(toDisplayM1, '1,000,000.000000001');
167
+ const toDisplayM2 = suiCoin.amountToString(suiMaster.MIST_PER_SUI * BigInt(2000000) + BigInt(900), {separateThousands: true});
168
+ t.equal(toDisplayM2, '2,000,000.0000009');
169
+
170
+ const toDisplayB1 = suiCoin.amountToString(suiMaster.MIST_PER_SUI * BigInt(1000000000) + BigInt(1), {separateThousands: true});
171
+ t.equal(toDisplayB1, '1,000,000,000.000000001');
172
+
173
+ const toDisplayT1 = suiCoin.amountToString(suiMaster.MIST_PER_SUI * BigInt(1000000000000) + BigInt(1), {separateThousands: true});
174
+ t.equal(toDisplayT1, '1,000,000,000,000.000000001');
175
+
176
+ const toDisplayT1q = suiCoin.amountToString(suiMaster.MIST_PER_SUI * BigInt(1000000000000) + BigInt(1), {separateThousands: ' '});
177
+ t.equal(toDisplayT1q, '1 000 000 000 000.000000001');
178
+ });
179
+
77
180
  test('you have no SUI on the fresh node', async t => {
78
181
  const suiCoin = suiMaster.suiCoins.get('sui');
79
182
  const balance = await suiCoin.getBalance(suiMaster.address);
@@ -88,6 +191,22 @@ test('have some after requesting from faucet', async t => {
88
191
  t.ok(balance > BigInt(0));
89
192
  });
90
193
 
194
+ test('have some in balance query', async t => {
195
+ const balances = await suiMaster.suiCoins.getAllBalances();
196
+
197
+ let ok = false;
198
+ for (const balance of balances) {
199
+ if (balance.coin.isSUI()) {
200
+ if (balance.totalBalance > 0n) {
201
+ ok = true;
202
+ }
203
+ }
204
+ }
205
+
206
+ t.ok(ok);
207
+ });
208
+
209
+
91
210
  test('getting coin objects for a transaction', async t => {
92
211
  const suiCoin = suiMaster.suiCoins.get('sui');
93
212
 
@@ -111,7 +230,6 @@ test('getting coin objects for a transaction', async t => {
111
230
  });
112
231
 
113
232
 
114
-
115
233
  test('stops local test node', async t => {
116
234
  await SuiLocalTestValidator.stop();
117
235
  });