suidouble 1.45.2 → 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.
Files changed (59) hide show
  1. package/.claude/settings.local.json +7 -0
  2. package/README.md +222 -131
  3. package/index.js +1 -3
  4. package/lib/SuiCliCommands.js +18 -25
  5. package/lib/SuiCoin.js +86 -138
  6. package/lib/SuiCoins.js +70 -31
  7. package/lib/SuiCommonMethods.js +40 -3
  8. package/lib/SuiEvent.js +54 -6
  9. package/lib/SuiInBrowser.js +145 -46
  10. package/lib/SuiInBrowserAdapter.js +164 -37
  11. package/lib/SuiLocalTestValidator.js +78 -25
  12. package/lib/SuiMaster.js +351 -126
  13. package/lib/SuiMemoryObjectStorage.js +66 -73
  14. package/lib/SuiObject.js +128 -153
  15. package/lib/SuiPackage.js +292 -187
  16. package/lib/SuiPackageModule.js +176 -221
  17. package/lib/SuiPaginatedResponse.js +288 -25
  18. package/lib/SuiPseudoRandomAddress.js +29 -2
  19. package/lib/SuiTransaction.js +115 -70
  20. package/lib/SuiUtils.js +179 -124
  21. package/package.json +30 -14
  22. package/test/build_modules.test.js +41 -0
  23. package/test/coins.test.js +17 -16
  24. package/test/custom_transaction.test.js +167 -0
  25. package/test/event_listeners.test.js +171 -0
  26. package/test/failed_transaction.test.js +184 -0
  27. package/test/name_service.test.js +28 -0
  28. package/test/owned_objects.test.js +148 -0
  29. package/test/rpc.test.js +3 -6
  30. package/test/sui_in_browser.test.js +2 -2
  31. package/test/sui_master_basic.test.js +4 -5
  32. package/test/sui_master_onlocal.test.js +84 -22
  33. package/test/sui_object_properties.test.js +85 -0
  34. package/test/test_move_contracts/different_types/Move.lock +18 -21
  35. package/test/test_move_contracts/different_types/sources/different_types.move +12 -12
  36. package/test/test_move_contracts/suidouble_chat/Move.lock +18 -22
  37. package/test/test_move_contracts/suidouble_chat/sources/suidouble_chat.move +9 -8
  38. package/tsconfig.json +15 -0
  39. package/types/index.d.ts +15 -0
  40. package/types/lib/SuiCliCommands.d.ts +6 -0
  41. package/types/lib/SuiCoin.d.ts +183 -0
  42. package/types/lib/SuiCoins.d.ts +93 -0
  43. package/types/lib/SuiCommonMethods.d.ts +37 -0
  44. package/types/lib/SuiEvent.d.ts +95 -0
  45. package/types/lib/SuiInBrowser.d.ts +189 -0
  46. package/types/lib/SuiInBrowserAdapter.d.ts +167 -0
  47. package/types/lib/SuiLocalTestValidator.d.ts +92 -0
  48. package/types/lib/SuiMaster.d.ts +333 -0
  49. package/types/lib/SuiMemoryObjectStorage.d.ts +96 -0
  50. package/types/lib/SuiObject.d.ts +135 -0
  51. package/types/lib/SuiPackage.d.ts +233 -0
  52. package/types/lib/SuiPackageModule.d.ts +139 -0
  53. package/types/lib/SuiPaginatedResponse.d.ts +148 -0
  54. package/types/lib/SuiPseudoRandomAddress.d.ts +33 -0
  55. package/types/lib/SuiTransaction.d.ts +92 -0
  56. package/types/lib/SuiUtils.d.ts +152 -0
  57. package/types/lib/data/icons.d.ts +12 -0
  58. package/lib/SuiTestScenario.js +0 -169
  59. package/test/sui_test_scenario.test.js +0 -61
@@ -0,0 +1,85 @@
1
+ 'use strict'
2
+
3
+ import t from 'tap';
4
+ import { SuiMaster, SuiLocalTestValidator } from '../index.js';
5
+
6
+ import { fileURLToPath } from 'url';
7
+ import path from 'path';
8
+
9
+ const { test } = t;
10
+ const __filename = fileURLToPath(import.meta.url);
11
+ const __dirname = path.dirname(__filename);
12
+
13
+ let suiLocalTestValidator = null;
14
+ let suiMaster = null;
15
+ let contract = null;
16
+
17
+ test('spawn local test node', async t => {
18
+ suiLocalTestValidator = await SuiLocalTestValidator.launch({ testFallbackEnabled: true });
19
+ t.ok(suiLocalTestValidator.active);
20
+ });
21
+
22
+ test('setup — init, fund, publish', async t => {
23
+ suiMaster = new SuiMaster({ client: suiLocalTestValidator, as: 'somebody', debug: false });
24
+ await suiMaster.initialize();
25
+
26
+ await suiMaster.requestSuiFromFaucet();
27
+
28
+ contract = suiMaster.addPackage({
29
+ path: path.join(__dirname, './test_move_contracts/suidouble_chat/'),
30
+ });
31
+ await contract.build();
32
+ await contract.publish();
33
+ t.ok(contract.address, 'contract published');
34
+ });
35
+
36
+ test('localProperties — stores arbitrary data without touching the chain', async t => {
37
+ const chatShop = suiMaster.objectStorage.findMostRecentByTypeName('ChatShop');
38
+ t.ok(chatShop, 'ChatShop found in objectStorage');
39
+
40
+ // initial state — empty object
41
+ t.type(chatShop.localProperties, 'object', 'localProperties is an object');
42
+ t.notOk(chatShop.localProperties.myKey, 'myKey not set initially');
43
+
44
+ // write
45
+ chatShop.localProperties.myKey = 'hello';
46
+ chatShop.localProperties.count = 42;
47
+
48
+ // read back from the same instance
49
+ t.equal(chatShop.localProperties.myKey, 'hello', 'myKey persists on the instance');
50
+ t.equal(chatShop.localProperties.count, 42, 'count persists on the instance');
51
+
52
+ // does NOT affect the object on chain — the object's fields are unrelated
53
+ t.notOk(chatShop.fields.myKey, 'myKey is not in on-chain fields');
54
+
55
+ // clear
56
+ delete chatShop.localProperties.myKey;
57
+ t.notOk(chatShop.localProperties.myKey, 'myKey removed after delete');
58
+ });
59
+
60
+ test('isImmutable — published package object is immutable', async t => {
61
+ // packages are always frozen / immutable on Sui after publishing
62
+ const packageObj = await suiMaster.getObject(contract.address);
63
+ t.ok(packageObj, 'package object fetched');
64
+ t.ok(packageObj.isImmutable, 'package object isImmutable is true');
65
+ t.notOk(packageObj.isShared, 'package object isShared is false');
66
+ });
67
+
68
+ test('display — fetchFields populates display property', async t => {
69
+ const chatShop = suiMaster.objectStorage.findMostRecentByTypeName('ChatShop');
70
+ t.ok(chatShop, 'ChatShop found');
71
+
72
+ await chatShop.fetchFields();
73
+
74
+ // display is always an object — {} when no Display template, otherwise keyed values
75
+ t.type(chatShop.display, 'object', 'display is an object after fetchFields');
76
+
77
+ // suidouble_chat has no Display template so we expect an empty map —
78
+ // but the field must exist and not throw
79
+ t.doesNotThrow(() => { void chatShop.display; }, 'accessing display does not throw');
80
+ });
81
+
82
+ test('stops local test node', async t => {
83
+ await SuiLocalTestValidator.stop().catch(() => {});
84
+ t.pass('stopped');
85
+ });
@@ -1,26 +1,23 @@
1
- # @generated by Move, please check-in and do not edit manually.
1
+ # Generated by move; do not edit
2
+ # This file should be checked in.
2
3
 
3
4
  [move]
4
- version = 3
5
- manifest_digest = "782E5DC5571D50504E8D0062C1C45607FF5A73378BE161077BCEF58ADEC1A3F5"
6
- deps_digest = "F8BBB0CCB2491CA29A3DF03D6F92277A4F3574266507ACD77214D37ECA3F3082"
7
- dependencies = [
8
- { id = "Sui", name = "Sui" },
9
- ]
5
+ version = 4
10
6
 
11
- [[move.package]]
12
- id = "MoveStdlib"
13
- source = { git = "https://github.com/MystenLabs/sui.git", rev = "testnet", subdir = "crates/sui-framework/packages/move-stdlib" }
7
+ [pinned.mainnet.MoveStdlib]
8
+ source = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/move-stdlib", rev = "d4a0c80be6020093592b305853832e7b80c5e2f2" }
9
+ use_environment = "mainnet"
10
+ manifest_digest = "C4FE4C91DE74CBF223B2E380AE40F592177D21870DC2D7EB6227D2D694E05363"
11
+ deps = {}
14
12
 
15
- [[move.package]]
16
- id = "Sui"
17
- source = { git = "https://github.com/MystenLabs/sui.git", rev = "testnet", subdir = "crates/sui-framework/packages/sui-framework" }
13
+ [pinned.mainnet.Sui]
14
+ source = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "d4a0c80be6020093592b305853832e7b80c5e2f2" }
15
+ use_environment = "mainnet"
16
+ manifest_digest = "CD547CB1ACCE0880C835DAED2D8FFCB91D56C833AE5240D3AA5B918398263195"
17
+ deps = { MoveStdlib = "MoveStdlib" }
18
18
 
19
- dependencies = [
20
- { id = "MoveStdlib", name = "MoveStdlib" },
21
- ]
22
-
23
- [move.toolchain-version]
24
- compiler-version = "1.44.2"
25
- edition = "2024.beta"
26
- flavor = "sui"
19
+ [pinned.mainnet.different_types]
20
+ source = { root = true }
21
+ use_environment = "mainnet"
22
+ manifest_digest = "EC6E90369603CE16A65E2F7B784DCFCA80948E3C176AD82DC6EB101BAA942A89"
23
+ deps = { Sui = "Sui" }
@@ -27,25 +27,25 @@ module different_types::different_types {
27
27
  })
28
28
  }
29
29
 
30
- public entry fun put_u8(store: &mut Store, value: u8, _ctx: &mut TxContext) {
30
+ public fun put_u8(store: &mut Store, value: u8, _ctx: &mut TxContext) {
31
31
  store.numbers = store.numbers + (value as u256);
32
32
  }
33
- public entry fun put_u16(store: &mut Store, value: u16, _ctx: &mut TxContext) {
33
+ public fun put_u16(store: &mut Store, value: u16, _ctx: &mut TxContext) {
34
34
  store.numbers = store.numbers + (value as u256);
35
35
  }
36
- public entry fun put_u32(store: &mut Store, value: u32, _ctx: &mut TxContext) {
36
+ public fun put_u32(store: &mut Store, value: u32, _ctx: &mut TxContext) {
37
37
  store.numbers = store.numbers + (value as u256);
38
38
  }
39
- public entry fun put_u64(store: &mut Store, value: u64, _ctx: &mut TxContext) {
39
+ public fun put_u64(store: &mut Store, value: u64, _ctx: &mut TxContext) {
40
40
  store.numbers = store.numbers + (value as u256);
41
41
  }
42
- public entry fun put_u128(store: &mut Store, value: u128, _ctx: &mut TxContext) {
42
+ public fun put_u128(store: &mut Store, value: u128, _ctx: &mut TxContext) {
43
43
  store.numbers = store.numbers + (value as u256);
44
44
  }
45
- public entry fun put_u256(store: &mut Store, value: u256, _ctx: &mut TxContext) {
45
+ public fun put_u256(store: &mut Store, value: u256, _ctx: &mut TxContext) {
46
46
  store.numbers = store.numbers + (value as u256);
47
47
  }
48
- public entry fun put_vector_u16(store: &mut Store, value: vector<u16>, _ctx: &mut TxContext) {
48
+ public fun put_vector_u16(store: &mut Store, value: vector<u16>, _ctx: &mut TxContext) {
49
49
  let vec_length = vector::length(&value);
50
50
  let mut i = 0;
51
51
  while (i < vec_length) {
@@ -54,18 +54,18 @@ module different_types::different_types {
54
54
  i = i + 1;
55
55
  };
56
56
  }
57
- public entry fun put_address(store: &mut Store, value: address, _ctx: &mut TxContext) {
57
+ public fun put_address(store: &mut Store, value: address, _ctx: &mut TxContext) {
58
58
  store.v_address = value;
59
59
  }
60
- public entry fun put_bool(store: &mut Store, value: bool, _ctx: &mut TxContext) {
60
+ public fun put_bool(store: &mut Store, value: bool, _ctx: &mut TxContext) {
61
61
  store.v_bool = value;
62
62
  }
63
- public entry fun put_string(store: &mut Store, value: String, _ctx: &mut TxContext) {
63
+ public fun put_string(store: &mut Store, value: String, _ctx: &mut TxContext) {
64
64
  store.v_string = value;
65
65
  }
66
66
 
67
- public entry fun put_type<T>(store: &mut Store, _ctx: &mut TxContext) {
68
- let typen = type_name::get<T>();
67
+ public fun put_type<T>(store: &mut Store, _ctx: &mut TxContext) {
68
+ let typen = type_name::with_defining_ids<T>();
69
69
  let type_as_string = typen.into_string(); // returns ascii string
70
70
 
71
71
  store.v_string = string::from_ascii(type_as_string);
@@ -1,27 +1,23 @@
1
- # @generated by Move, please check-in and do not edit manually.
1
+ # Generated by move; do not edit
2
+ # This file should be checked in.
2
3
 
3
4
  [move]
4
- version = 3
5
- manifest_digest = "F8C73BB1CA5B2EEF078E6FD0C793EF387322A4AD49DECCFE6AAD9F5F81C198C8"
6
- deps_digest = "F8BBB0CCB2491CA29A3DF03D6F92277A4F3574266507ACD77214D37ECA3F3082"
5
+ version = 4
7
6
 
8
- dependencies = [
9
- { id = "Sui", name = "Sui" },
10
- ]
7
+ [pinned.mainnet.MoveStdlib]
8
+ source = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/move-stdlib", rev = "d4a0c80be6020093592b305853832e7b80c5e2f2" }
9
+ use_environment = "mainnet"
10
+ manifest_digest = "C4FE4C91DE74CBF223B2E380AE40F592177D21870DC2D7EB6227D2D694E05363"
11
+ deps = {}
11
12
 
12
- [[move.package]]
13
- id = "MoveStdlib"
14
- source = { git = "https://github.com/MystenLabs/sui.git", rev = "testnet", subdir = "crates/sui-framework/packages/move-stdlib" }
13
+ [pinned.mainnet.Sui]
14
+ source = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "d4a0c80be6020093592b305853832e7b80c5e2f2" }
15
+ use_environment = "mainnet"
16
+ manifest_digest = "CD547CB1ACCE0880C835DAED2D8FFCB91D56C833AE5240D3AA5B918398263195"
17
+ deps = { MoveStdlib = "MoveStdlib" }
15
18
 
16
- [[move.package]]
17
- id = "Sui"
18
- source = { git = "https://github.com/MystenLabs/sui.git", rev = "testnet", subdir = "crates/sui-framework/packages/sui-framework" }
19
-
20
- dependencies = [
21
- { id = "MoveStdlib", name = "MoveStdlib" },
22
- ]
23
-
24
- [move.toolchain-version]
25
- compiler-version = "1.44.2"
26
- edition = "2024"
27
- flavor = "sui"
19
+ [pinned.mainnet.suidouble_chat]
20
+ source = { root = true }
21
+ use_environment = "mainnet"
22
+ manifest_digest = "EC6E90369603CE16A65E2F7B784DCFCA80948E3C176AD82DC6EB101BAA942A89"
23
+ deps = { Sui = "Sui" }
@@ -93,7 +93,7 @@ module suidouble_chat::suidouble_chat {
93
93
  // }
94
94
 
95
95
  /// Mint (post) a ChatTopMessage object without referencing another object.
96
- public entry fun post(
96
+ public fun post(
97
97
  chat_shop: &ChatShop,
98
98
  text: vector<u8>,
99
99
  metadata: vector<u8>,
@@ -128,7 +128,7 @@ module suidouble_chat::suidouble_chat {
128
128
  }
129
129
 
130
130
  /// Mint (post) a ChatTopMessage object without referencing another object.
131
- public entry fun post_pay(
131
+ public fun post_pay(
132
132
  chat_shop: &mut ChatShop,
133
133
  sui: Coin<SUI>,
134
134
  text: vector<u8>,
@@ -169,7 +169,7 @@ module suidouble_chat::suidouble_chat {
169
169
  transfer::share_object(chat_top_message);
170
170
  }
171
171
 
172
- public entry fun post_pay_with_coin_vector(
172
+ public fun post_pay_with_coin_vector(
173
173
  chat_shop: &mut ChatShop,
174
174
  coins: vector<Coin<SUI>>,
175
175
  text: vector<u8>,
@@ -182,7 +182,8 @@ module suidouble_chat::suidouble_chat {
182
182
  }
183
183
 
184
184
  /// Mint (post) a ChatResponse object
185
- public entry fun reply(
185
+ #[allow(lint(self_transfer))]
186
+ public fun reply(
186
187
  chat_top_message: &mut ChatTopMessage,
187
188
  text: vector<u8>,
188
189
  metadata: vector<u8>,
@@ -215,7 +216,7 @@ module suidouble_chat::suidouble_chat {
215
216
  }
216
217
 
217
218
  /// Permanently delete `ChatResponse`
218
- public entry fun burn_response(chat_response: ChatResponse, _: &mut TxContext) {
219
+ public fun burn_response(chat_response: ChatResponse, _: &mut TxContext) {
219
220
  let ChatResponse { id, chat_top_message_id: _, author: _, text: _, metadata: _, seq_n: _ } = chat_response;
220
221
  object::delete(id)
221
222
  }
@@ -260,7 +261,8 @@ module suidouble_chat::suidouble_chat {
260
261
  // }
261
262
 
262
263
  /// Mint a lot of responses (we need this to unit test SuiPaginatedResponse faster)
263
- public entry fun fill(
264
+ #[allow(lint(self_transfer))]
265
+ public fun fill(
264
266
  chat_top_message: &mut ChatTopMessage,
265
267
  text: vector<u8>,
266
268
  metadata: vector<u8>,
@@ -336,7 +338,6 @@ module suidouble_chat::suidouble_chat {
336
338
  let chat_top_message = test_scenario::take_shared<ChatTopMessage>(scenario);
337
339
  // let chat_shop_ref = &chat_shop;
338
340
  debug::print(&chat_top_message);
339
- debug::print(&mut chat_top_message);
340
341
 
341
342
  // let chat_top_message_ref = &chat_top_message;
342
343
  reply(&mut chat_top_message, b"response", b"metadata", test_scenario::ctx(scenario));
@@ -368,7 +369,7 @@ module suidouble_chat::suidouble_chat {
368
369
  // let chat_top_message = test_scenario::take_from_sender<ChatTopMessage>(scenario);
369
370
  let chat_top_message = test_scenario::take_shared<ChatTopMessage>(scenario);
370
371
  // let chat_shop_ref = &chat_shop;
371
- debug::print(&mut chat_top_message);
372
+ debug::print(&chat_top_message);
372
373
 
373
374
  // let chat_top_message_ref = &chat_top_message;
374
375
  reply(&mut chat_top_message, b"response", b"metadata", test_scenario::ctx(scenario));
package/tsconfig.json ADDED
@@ -0,0 +1,15 @@
1
+ {
2
+ "compilerOptions": {
3
+ "allowJs": true,
4
+ "declaration": true,
5
+ "emitDeclarationOnly": true,
6
+ "declarationDir": "./types",
7
+ "module": "ESNext",
8
+ "moduleResolution": "bundler",
9
+ "target": "ES2020",
10
+ "strict": false,
11
+ "skipLibCheck": true,
12
+ "checkJs": false
13
+ },
14
+ "include": ["index.js", "lib/*.js"]
15
+ }
@@ -0,0 +1,15 @@
1
+ import SuiMaster from './lib/SuiMaster.js';
2
+ import SuiObject from './lib/SuiObject.js';
3
+ import SuiInBrowser from './lib/SuiInBrowser.js';
4
+ import SuiLocalTestValidator from './lib/SuiLocalTestValidator.js';
5
+ export const MIST_PER_SUI: bigint;
6
+ import { Transaction } from '@mysten/sui/transactions';
7
+ import { TransactionCommands as Commands } from '@mysten/sui/transactions';
8
+ import SuiUtils from './lib/SuiUtils.js';
9
+ export const txInput: typeof SuiUtils.txInput;
10
+ import { bcs } from '@mysten/sui/bcs';
11
+ import SuiMemoryObjectStorage from './lib/SuiMemoryObjectStorage.js';
12
+ import SuiCoin from './lib/SuiCoin.js';
13
+ import SuiCoins from './lib/SuiCoins.js';
14
+ import SuiPaginatedResponse from './lib/SuiPaginatedResponse.js';
15
+ export { SuiMaster, SuiObject, SuiInBrowser, SuiLocalTestValidator, Transaction, Commands, SuiUtils, bcs, SuiMemoryObjectStorage, SuiCoin, SuiCoins, SuiPaginatedResponse };
@@ -0,0 +1,6 @@
1
+ export default class SuiCliCommands {
2
+ static isPortThere(port: any): Promise<any>;
3
+ static spawn(command: any, params?: any[], envVars?: {}): Promise<any>;
4
+ static exec(command: any): Promise<any>;
5
+ static getModulesNamesFromPackagePath(path: any): Promise<any>;
6
+ }
@@ -0,0 +1,183 @@
1
+ /**
2
+ * @typedef {import("@mysten/sui/transactions").TransactionObjectArgument} TransactionObjectArgument
3
+ *
4
+ * @import { SuiClientTypes } from "@mysten/sui/client"
5
+ *
6
+ * @typedef CoinMeta
7
+ * @type {object}
8
+ * @property {number} decimals - Number of decimal places the coin uses.
9
+ * @property {string} description - Description of the token
10
+ * @property {string} iconUrl - URL for the token logo
11
+ * @property {string} name - Name for the token
12
+ * @property {string} symbol - Symbol for the token
13
+ * @property {string} [id] - Meta id
14
+ * @property {string} [type] - Coin type string
15
+ *
16
+ *
17
+ * @typedef {SuiClientTypes.Balance & { coin: SuiCoin, totalBalance: bigint }} SuidoubleCoinBalance
18
+ * @typedef {import("./SuiMaster.js").default} SuiMaster
19
+ * @typedef {import("./SuiCoins.js").default} SuiCoins
20
+ */
21
+ /**
22
+ * Handle for a single coin type (e.g. `0x2::sui::SUI`). Caches metadata, formats amounts
23
+ * via decimals, and builds `Coin<T>` arguments for transactions.
24
+ */
25
+ export default class SuiCoin {
26
+ /**
27
+ * Returns true if the object looks like a usable CoinMeta (has positive `decimals`, `name`, `symbol`).
28
+ * @param {CoinMeta} meta
29
+ * @returns {boolean}
30
+ */
31
+ static isValidMetadata(meta: CoinMeta): boolean;
32
+ /**
33
+ * SuiCoin constructor
34
+ * @param {Object} params - Initialization parameters
35
+ * @param {string} params.coinType - sui object type for a coin, without Coin<...>, only the inside type
36
+ * @param {SuiCoins} params.suiCoins - instance of SuiCoins
37
+ */
38
+ constructor(params: {
39
+ coinType: string;
40
+ suiCoins: SuiCoins;
41
+ });
42
+ _coinType: string;
43
+ _suiCoins: import("./SuiCoins.js").default;
44
+ _exists: boolean;
45
+ _metadata: CoinMeta | SuiClientTypes.CoinMetadata;
46
+ /**
47
+ * Normalize amount based on .decimals. Pass a string with a dot ('5.22', '0.0005') to convert it to units
48
+ * always use a dot, event for '1.0' or '100.0'.
49
+ * @param {String|Number|BigInt} amount
50
+ * @returns {BigInt}
51
+ */
52
+ normalizeAmount(amount: string | number | bigint): bigint;
53
+ /**
54
+ * 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.
55
+ * @param {String|Number|bigint} amount
56
+ * @returns {Promise.<bigint>}
57
+ */
58
+ lazyNormalizeAmount(amount: string | number | bigint): Promise<bigint>;
59
+ /**
60
+ * Get readable representation of a raw amount (bigint-native, NOT a pre-formatted "1.99" string),
61
+ * based on coin decimals metadata (requires metadata to be loaded or set).
62
+ *
63
+ * @param {bigint|number|string} amount - raw amount in the coin's base units
64
+ * @param {Object} [options] - format options
65
+ * @param {boolean} [options.withAbbr] - append K/M/B/T for large amounts (Suiet-style)
66
+ * @param {boolean|string} [options.separateThousands] - separate thousands by `,` (true) or by a custom delimiter
67
+ * @returns {string}
68
+ */
69
+ amountToString(amount: bigint | number | string, options?: {
70
+ withAbbr?: boolean;
71
+ separateThousands?: boolean | string;
72
+ }): string;
73
+ /**
74
+ * Format large amounts.
75
+ *
76
+ * thanks @bruceeewong and @suiet
77
+ *
78
+ * @param {bigint} amount
79
+ * @param {bigint} measureUnit - divisor for the unit (1_000n for K, 1_000_000n for M, …)
80
+ * @param {string} abbrSymbol - suffix to append (K, M, B, T)
81
+ * @param {boolean|string} [separateThousands=false] - separate thousands by `,` (true) or by a custom delimiter
82
+ * @returns {string}
83
+ */
84
+ formatWithAbbr(amount: bigint, measureUnit: bigint, abbrSymbol: string, separateThousands?: boolean | string): string;
85
+ /**
86
+ * @type {SuiMaster}
87
+ */
88
+ get suiMaster(): SuiMaster;
89
+ /** @returns {string} coin type string, always prefixed with `0x` */
90
+ get coinType(): string;
91
+ /**
92
+ * Move type for the Coin object of this coin type
93
+ *
94
+ * @type {string}
95
+ */
96
+ get coinObjectType(): string;
97
+ /** @returns {number | undefined} decimals from loaded metadata, or `undefined` if not yet loaded */
98
+ get decimals(): number | undefined;
99
+ /** @returns {?CoinMeta} loaded coin metadata, or null if not loaded */
100
+ get metadata(): CoinMeta | null;
101
+ /** @returns {?string} coin symbol from metadata, or null if metadata isn't loaded */
102
+ get symbol(): string | null;
103
+ /** @returns {?string} coin name from metadata, or null if metadata isn't loaded */
104
+ get name(): string | null;
105
+ /**
106
+ * True if this coin's type is the normalized SUI type (`0x2::sui::SUI` expanded to 64 hex chars).
107
+ * @returns {boolean}
108
+ */
109
+ isSUI(): boolean;
110
+ /**
111
+ * set predefined coin metadata so it will not be fetched from RPC
112
+ * @param {CoinMeta} meta
113
+ *
114
+ * @returns {boolean} if processed ok
115
+ */
116
+ setMetadata(meta: CoinMeta): boolean;
117
+ /**
118
+ * Load coin metadata from the blockchain. Concurrent callers share the same in-flight request.
119
+ * As a good pattern, prefer hard-coded / cached metadata set via `suiMaster.suiCoins.setCoinMetas(...)`.
120
+ *
121
+ * @returns {Promise<?CoinMeta>} resolved metadata, or `null` if the coin type has none on chain
122
+ */
123
+ getMetadata(): Promise<CoinMeta | null>;
124
+ __getMetadataResolver: (value: any) => void;
125
+ __getMetadataPromise: Promise<any>;
126
+ /**
127
+ * Get coin balance of the wallet
128
+ * @param {string} owner
129
+ *
130
+ * @returns {Promise.<bigint>}
131
+ */
132
+ getBalance(owner: string): Promise<bigint>;
133
+ /**
134
+ * Return a TransactionObjectArgument with a Coin of the requested amount, ready to use in moveCall.
135
+ * Delegates to the v2 SDK's `tx.coinWithBalance` intent, which at build time fetches all owned
136
+ * coins of this type, merges them (including zero-balance dust), and splits off the requested amount.
137
+ *
138
+ * @param {Transaction} txb - Native SUI SDK Transaction
139
+ * @param {string} _owner - unused; kept for signature compatibility. The resolver picks coins owned by the tx sender.
140
+ * @param {BigInt|string} amount - amount of coin. BigInt or string normalized via Coin decimals ("0.05" → 0.05 SUI)
141
+ * @returns {Promise.<TransactionObjectArgument>}
142
+ */
143
+ coinOfAmountToTxCoin(txb: Transaction, _owner: string, amount: bigint | string): Promise<TransactionObjectArgument>;
144
+ }
145
+ export type TransactionObjectArgument = import("@mysten/sui/transactions").TransactionObjectArgument;
146
+ export type CoinMeta = {
147
+ /**
148
+ * - Number of decimal places the coin uses.
149
+ */
150
+ decimals: number;
151
+ /**
152
+ * - Description of the token
153
+ */
154
+ description: string;
155
+ /**
156
+ * - URL for the token logo
157
+ */
158
+ iconUrl: string;
159
+ /**
160
+ * - Name for the token
161
+ */
162
+ name: string;
163
+ /**
164
+ * - Symbol for the token
165
+ */
166
+ symbol: string;
167
+ /**
168
+ * - Meta id
169
+ */
170
+ id?: string;
171
+ /**
172
+ * - Coin type string
173
+ */
174
+ type?: string;
175
+ };
176
+ export type SuidoubleCoinBalance = SuiClientTypes.Balance & {
177
+ coin: SuiCoin;
178
+ totalBalance: bigint;
179
+ };
180
+ export type SuiMaster = import("./SuiMaster.js").default;
181
+ export type SuiCoins = import("./SuiCoins.js").default;
182
+ import type { SuiClientTypes } from "@mysten/sui/client";
183
+ import { Transaction } from '@mysten/sui/transactions';
@@ -0,0 +1,93 @@
1
+ /**
2
+ * @typedef {import("./SuiCoin.js").CoinMeta} CoinMeta
3
+ * @typedef {import("./SuiCoin.js").SuidoubleCoinBalance} SuidoubleCoinBalance
4
+ * @typedef {import("./SuiMaster.js").default} SuiMaster
5
+ */
6
+ /**
7
+ * Common class to work with Coins and Coin objects. Expected to have single instance per SuiMaster instance
8
+ * @class
9
+ * @constructor
10
+ * @public
11
+ */
12
+ export default class SuiCoins extends SuiCommonMethods {
13
+ /**
14
+ * Fetch the mainnet coin metadata bundle from `coinmeta.polymedia.app` and cache the promise so
15
+ * concurrent callers share a single request. Failures are swallowed and resolve to an empty array.
16
+ *
17
+ * @returns {Promise<Array.<CoinMeta>>} list of CoinMeta records, or an empty array on failure
18
+ */
19
+ static prefetchMainnetCoinMetas(): Promise<Array<CoinMeta>>;
20
+ static _singleInstances: {};
21
+ /**
22
+ * Return singleton instance of the SuiCoins object for the specific chain
23
+ *
24
+ * @param {Object} params - parameters
25
+ * @param {SuiMaster} params.suiMaster - instance of SuiMaster
26
+ * @returns {SuiCoins}
27
+ */
28
+ static getSingleton(params: {
29
+ suiMaster: SuiMaster;
30
+ }): SuiCoins;
31
+ /**
32
+ * SuiCoins constructor
33
+ * @param {Object} params - Initialization parameters
34
+ * @param {SuiMaster} params.suiMaster - instance of SuiMaster
35
+ * @param {boolean} [params.debug]
36
+ */
37
+ constructor(params: {
38
+ suiMaster: SuiMaster;
39
+ debug?: boolean;
40
+ });
41
+ /** @type {SuiMaster} */
42
+ _suiMaster: SuiMaster;
43
+ /** @type {Object.<string, SuiCoin>} */
44
+ _coins: {
45
+ [x: string]: SuiCoin;
46
+ };
47
+ /**
48
+ * @type {SuiMaster}
49
+ */
50
+ get suiMaster(): SuiMaster;
51
+ /** @returns {Object.<string, SuiCoin>} map of coinType → SuiCoin instance */
52
+ get coins(): {
53
+ [x: string]: SuiCoin;
54
+ };
55
+ /**
56
+ * Set predefined coin metas so they will not need to be fetched from RPC.
57
+ *
58
+ * @param {Object.<string, CoinMeta> | Array.<CoinMeta>} coinMetas - keyed map by coin type, or an array of CoinMeta with `type` field
59
+ * @returns {number} count of processed items
60
+ */
61
+ setCoinMetas(coinMetas: {
62
+ [x: string]: CoinMeta;
63
+ } | Array<CoinMeta>): number;
64
+ /**
65
+ * Get all CoinBalance[] for the specific address or connected address.
66
+ *
67
+ * @param {Object} [params]
68
+ * @param {?string} [params.owner] - owner address; if omitted, uses the connected SuiMaster address
69
+ * @returns {Promise<Array<SuidoubleCoinBalance>>}
70
+ */
71
+ getAllBalances(params?: {
72
+ owner?: string | null;
73
+ }): Promise<Array<SuidoubleCoinBalance>>;
74
+ /**
75
+ * normalize coinType string to sui's coin type. As extra, may take 'sui' or 'SUI' as the type and return type for it
76
+ * @param {string} coinType
77
+ * @returns {string} normalized coin type
78
+ */
79
+ normalizeCoinType(coinType: string): string;
80
+ /**
81
+ * Return instance of SuiCoin of specific type. The result is cached per normalized coin type,
82
+ * so repeated calls with equivalent inputs return the same instance.
83
+ *
84
+ * @param {string} coinType - MoveType, or 'SUI' as helper
85
+ * @returns {SuiCoin}
86
+ */
87
+ get(coinType: string): SuiCoin;
88
+ }
89
+ export type CoinMeta = import("./SuiCoin.js").CoinMeta;
90
+ export type SuidoubleCoinBalance = import("./SuiCoin.js").SuidoubleCoinBalance;
91
+ export type SuiMaster = import("./SuiMaster.js").default;
92
+ import SuiCommonMethods from './SuiCommonMethods.js';
93
+ import SuiCoin from './SuiCoin.js';
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Base class for suidouble domain objects. Extends `EventTarget` so subclasses can emit
3
+ * events via `this.emit(...)` and consumers can subscribe via `addEventListener(...)`.
4
+ * Also provides a debug-gated `log(...)` helper.
5
+ */
6
+ export default class SuiCommonMethods extends EventTarget {
7
+ /**
8
+ * @param {Object} [params]
9
+ * @param {boolean} [params.debug] - enable debug logging via `log(...)`
10
+ */
11
+ constructor(params?: {
12
+ debug?: boolean;
13
+ });
14
+ _debug: boolean;
15
+ /**
16
+ * Debug logger. No-op unless the instance was constructed with `debug: true`.
17
+ * Prefixes messages with the owning SuiMaster's instance number (if available) and the class name.
18
+ * @param {...any} args
19
+ */
20
+ log(...args: any[]): void;
21
+ /**
22
+ * Dispatch an event to registered `addEventListener` subscribers.
23
+ *
24
+ * If `data` is a `SuiEvent` (has `isSuiEvent === true`) and `forceCustom` is falsy, it is dispatched
25
+ * directly so its own `.type` (the Move event name) is used — this lets consumers
26
+ * `addEventListener('ChatShopCreated', …)` without wrapping. Otherwise dispatches a `CustomEvent`
27
+ * of type `eventType` with `data` placed on the event's `detail` field.
28
+ *
29
+ * Any dispatch errors are caught and logged to `console.error` so a buggy listener can't abort the
30
+ * surrounding flow.
31
+ *
32
+ * @param {string} eventType - event name when wrapping in a CustomEvent (ignored for direct SuiEvent dispatch)
33
+ * @param {*} data - payload; SuiEvent is dispatched directly, anything else is wrapped
34
+ * @param {boolean} [forceCustom=false] - if true, always wrap in a CustomEvent even for SuiEvent payloads
35
+ */
36
+ emit(eventType: string, data: any, forceCustom?: boolean): void;
37
+ }