suidouble 2.5.0 → 2.17.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 (57) hide show
  1. package/.claude/settings.local.json +7 -0
  2. package/README.md +222 -131
  3. package/index.js +0 -2
  4. package/lib/SuiCliCommands.js +18 -25
  5. package/lib/SuiCoin.js +79 -137
  6. package/lib/SuiCoins.js +41 -29
  7. package/lib/SuiCommonMethods.js +40 -3
  8. package/lib/SuiEvent.js +54 -6
  9. package/lib/SuiInBrowser.js +143 -15
  10. package/lib/SuiInBrowserAdapter.js +185 -40
  11. package/lib/SuiLocalTestValidator.js +76 -14
  12. package/lib/SuiMaster.js +335 -139
  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 -127
  21. package/package.json +29 -13
  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 -0
  35. package/test/test_move_contracts/suidouble_chat/Move.lock +18 -0
  36. package/tsconfig.json +15 -0
  37. package/types/index.d.ts +15 -0
  38. package/types/lib/SuiCliCommands.d.ts +6 -0
  39. package/types/lib/SuiCoin.d.ts +183 -0
  40. package/types/lib/SuiCoins.d.ts +93 -0
  41. package/types/lib/SuiCommonMethods.d.ts +37 -0
  42. package/types/lib/SuiEvent.d.ts +95 -0
  43. package/types/lib/SuiInBrowser.d.ts +189 -0
  44. package/types/lib/SuiInBrowserAdapter.d.ts +171 -0
  45. package/types/lib/SuiLocalTestValidator.d.ts +92 -0
  46. package/types/lib/SuiMaster.d.ts +333 -0
  47. package/types/lib/SuiMemoryObjectStorage.d.ts +96 -0
  48. package/types/lib/SuiObject.d.ts +135 -0
  49. package/types/lib/SuiPackage.d.ts +233 -0
  50. package/types/lib/SuiPackageModule.d.ts +139 -0
  51. package/types/lib/SuiPaginatedResponse.d.ts +148 -0
  52. package/types/lib/SuiPseudoRandomAddress.d.ts +33 -0
  53. package/types/lib/SuiTransaction.d.ts +92 -0
  54. package/types/lib/SuiUtils.d.ts +152 -0
  55. package/types/lib/data/icons.d.ts +12 -0
  56. package/lib/SuiTestScenario.js +0 -169
  57. package/test/sui_test_scenario.test.js +0 -61
@@ -0,0 +1,152 @@
1
+ export { normalizeSuiAddress };
2
+ /** Helpful methods using in different places of suidouble */
3
+ export default class SuiUtils extends SuiCommonMethods {
4
+ /**
5
+ * Attach the parameter input into transaction, to be used for moveCall
6
+ * accepts an Inputs.Pure (result of .pureInput) or type + value directly
7
+ *
8
+ * @param {Transaction} tx
9
+ * @param {string | PureInput} typeOrInput - string type name, or already-serialised Pure input `{ Pure: { bytes } }`
10
+ * @param {*} [value]
11
+ * @returns {Argument}
12
+ */
13
+ static txInput(tx: Transaction, typeOrInput: string | PureInput, value?: any): Argument;
14
+ /**
15
+ * Returns and Inputs.Pure for a given type
16
+ * to be used as moveCall parameters
17
+ * type is 'u8', 'u16', 'u32', 'u64', 'u128', 'u256', 'address', 'bool', 'string', 'vector<u8>' ... 'vector<u256>'
18
+ *
19
+ * result may be passed as arguments to SuiPackage or SuiPackageModule moveCall functions params array:
20
+ * contract.moveCall('suidouble_chat', 'reply', [
21
+ * SuiUtils.pureInput('string', 'metadata')
22
+ * SuiUtils.pureInput('string', 'metadata')
23
+ * ]);
24
+ *
25
+ * if you are going to construct tx yourself, you'd better use SuiUtils.txInput static method
26
+ *
27
+ * @param {string} type
28
+ * @param {*} value
29
+ * @returns {CallArg}
30
+ */
31
+ static pureInput(type: string, value: any): CallArg;
32
+ /**
33
+ * Convert sui's PureInput into bcs serialized bytes
34
+ * @param {PureInput} pureInput
35
+ */
36
+ static pureInputToBytes(pureInput: PureInput): Uint8Array<ArrayBuffer>;
37
+ /**
38
+ * Decode a Move `vector<u8>` field into a UTF-8 string.
39
+ *
40
+ * Accepts the shapes SUI returns across representations:
41
+ * - base64 string (v2 gRPC/GraphQL JSON representation for byte vectors)
42
+ * - Uint8Array
43
+ * - array of numbers (legacy JSON-RPC shape)
44
+ *
45
+ * @param {string | Uint8Array | number[]} value
46
+ * @returns {string}
47
+ */
48
+ static bytesFieldToString(value: string | Uint8Array | number[]): string;
49
+ /**
50
+ * Wrapper for sui's utils normalizeSuiAddress
51
+ * Perform the following operations:
52
+ * <pre>
53
+ * 1. Make the address lower case
54
+ * 2. Prepend `0x` if the string does not start with `0x`.
55
+ * 3. Add more zeros if the length of the address(excluding `0x`) is less than `SUI_ADDRESS_LENGTH`
56
+ * </pre>
57
+ *
58
+ * @param {string} address
59
+ * @returns string
60
+ */
61
+ static normalizeSuiAddress(address: string): string;
62
+ /**
63
+ * Makes an instance of SuiGrpcClient pointed at a custom gRPC-web endpoint.
64
+ *
65
+ * `transportOptions` is passed through to GrpcWebFetchTransport — the same shape
66
+ * as `@protobuf-ts/grpcweb-transport`'s GrpcWebOptions:
67
+ * - baseUrl : string — required, the gRPC-web endpoint
68
+ * - format : 'text' | 'binary' — wire format, defaults to 'text'
69
+ * - fetchInit : RequestInit-ish — extra fetch options (credentials, cache, ...); `body`/`headers`/`method`/`signal` are reserved
70
+ * - fetch : typeof fetch — custom fetch implementation (useful for proxies, auth, logging)
71
+ *
72
+ * @example
73
+ * const client = SuiUtils.suiClientForRPC('mainnet', {
74
+ * baseUrl: 'https://fullnode.mainnet.sui.io:443',
75
+ * format: 'binary',
76
+ * fetchInit: { credentials: 'include' },
77
+ * fetch: (url, init) => fetch(url, { ...init, headers: { ...init.headers, 'x-api-key': 'xxx' } }),
78
+ * });
79
+ *
80
+ * @param {SuiClientTypes.Network} network
81
+ * @param {GrpcWebOptions} transportOptions
82
+ * @returns {SuiGrpcClient}
83
+ */
84
+ static suiClientForRPC(network: SuiClientTypes.Network, transportOptions: GrpcWebOptions): SuiGrpcClient;
85
+ /**
86
+ * Build a SuiGraphQLClient reusing the network of an existing SuiGrpcClient.
87
+ *
88
+ * Picks the default Sui GraphQL endpoint for the network unless `overrides.url` is set.
89
+ * `overrides` is forwarded to SuiGraphQLClient (fetch, headers, queries, mvr, url).
90
+ *
91
+ * @param {SuiGrpcClient} grpcClient
92
+ * @param {Object} [overrides]
93
+ * @param {?string} [overrides.url]
94
+ * @param {?typeof fetch} [overrides.fetch]
95
+ * @param {?Object.<string, string>} [overrides.headers]
96
+ * @returns {SuiGraphQLClient}
97
+ */
98
+ static suiGraphQLClientFromGrpc(grpcClient: SuiGrpcClient, overrides?: {
99
+ url?: string | null;
100
+ fetch?: typeof fetch | null;
101
+ headers?: {
102
+ [x: string]: string;
103
+ } | null;
104
+ }): SuiGraphQLClient;
105
+ /**
106
+ * Makes an instance for SuiGrpcClient for a specific chain, eg: 'mainnet' | 'testnet' | 'devnet' | 'localnet'
107
+ * @param {SuiClientTypes.Network} network
108
+ * @returns {SuiGrpcClient}
109
+ */
110
+ static suiClientFor(network: SuiClientTypes.Network): SuiGrpcClient;
111
+ /**
112
+ * Normalize client parameter into a SuiGrpcClient, accepting:
113
+ * - an existing SuiGrpcClient instance
114
+ * - a SuiLocalTestValidator instance
115
+ * - a string chain name: 'local' | 'localnet' | 'dev' | 'devnet' | 'test' | 'testnet' | 'main' | 'mainnet'
116
+ * - a legacy client object (sniffs network from endpoint / connection.fullnode / providerName)
117
+ *
118
+ * @param {SuiGrpcClient | string | Object} clientParam
119
+ * @returns {SuiGrpcClient | null}
120
+ */
121
+ static normalizeClient(clientParam: SuiGrpcClient | string | any): SuiGrpcClient | null;
122
+ /**
123
+ * Strip an optional "sui:" prefix and map short aliases ('local', 'dev', 'test', 'main')
124
+ * to full network names. Returns null if the string doesn't match a known network.
125
+ *
126
+ * @param {string} s
127
+ * @returns {SuiClientTypes.Network | null}
128
+ */
129
+ static normalizeNetworkString(s: string): SuiClientTypes.Network | null;
130
+ /**
131
+ * Extracts a SuiClientTypes.Network string from various inputs used historically by suidouble.
132
+ *
133
+ * @param {string | Object} clientParam
134
+ * @returns {SuiClientTypes.Network | null}
135
+ */
136
+ static _sniffNetwork(clientParam: string | any): SuiClientTypes.Network | null;
137
+ }
138
+ export type Argument = import("@mysten/sui/transactions").Argument;
139
+ export type CallArg = import("@mysten/sui/transactions").CallArg;
140
+ export type PureInput = {
141
+ Pure: {
142
+ bytes: string;
143
+ };
144
+ };
145
+ export type SuiGrpcClientOptions = import("@mysten/sui/grpc").SuiGrpcClientOptions;
146
+ export type GrpcWebOptions = import("@mysten/sui/grpc").GrpcWebOptions;
147
+ import { normalizeSuiAddress } from '@mysten/sui/utils';
148
+ import SuiCommonMethods from './SuiCommonMethods.js';
149
+ import { Transaction } from '@mysten/sui/transactions';
150
+ import type { SuiClientTypes } from "@mysten/sui/client";
151
+ import { SuiGrpcClient } from '@mysten/sui/grpc';
152
+ import { SuiGraphQLClient } from '@mysten/sui/graphql';
@@ -0,0 +1,12 @@
1
+ export default icons;
2
+ declare namespace icons {
3
+ let SLUSH: string;
4
+ let OKX: string;
5
+ let PHANTOM: string;
6
+ let SUI: string;
7
+ let SUIET: string;
8
+ let GLASS: string;
9
+ let ETHOS: string;
10
+ let SURF: string;
11
+ let NIGHTLY: string;
12
+ }
@@ -1,169 +0,0 @@
1
- import SuiCommonMethods from './SuiCommonMethods.js';
2
- import SuiLocalTestValidator from './SuiLocalTestValidator.js';
3
- import SuiMaster from './SuiMaster.js';
4
- import SuiUtils from './SuiUtils.js';
5
-
6
-
7
- export default class SuiTestScenario extends SuiCommonMethods {
8
- constructor(params = {}) {
9
- super(params);
10
-
11
- this._path = params.path; // path to Move package's root
12
- this._client = null;
13
-
14
- this._defaultAs = null; // 'as'(string for pseudo-random keypair generator) for default user and package's owner
15
- // (we will publish and init from this user)
16
- this._currentAs = null; // 'as' for current wrapped transaction
17
-
18
- this._masters = { // suiMaster and package for each 'as'
19
- };
20
- this._packages = {
21
- };
22
-
23
- this._publishedPackageId = null;
24
- }
25
-
26
- get currentAs() {
27
- return this._currentAs;
28
- }
29
-
30
- arg(type, value) {
31
- return SuiUtils.pureInput(type, value);
32
- }
33
-
34
- /**
35
- * Start local test validator and set up `as` as owner of package deploy transaction.
36
- * Package will be deployed with method `init`, as we try to mimic Sui Move's test_scenario
37
- * @param {String} as
38
- */
39
- async begin(as) {
40
- this._client = await SuiLocalTestValidator.launch({debug: true});
41
- this._defaultAs = as;
42
- this._currentAs = as;
43
- }
44
-
45
- /**
46
- * Shut down test validator and finish test scenario
47
- */
48
- async end() {
49
- await SuiLocalTestValidator.stop();
50
- }
51
-
52
- /**
53
- * Deploy the package. Move will execute it's init function.
54
- */
55
- async init() {
56
- if (!this._defaultAs) {
57
- throw new Error('please call .begin(as) first');
58
- }
59
-
60
- this._currentAs = this._defaultAs;
61
- await this.initMaster(this._defaultAs);
62
- }
63
-
64
-
65
- /**
66
- * Temorary assign user to `as`
67
- * @param {String} as
68
- * @param {Function} func
69
- */
70
- async next_tx(as, func) {
71
- if (!this._defaultAs) {
72
- throw new Error('please call .begin(as) first');
73
- }
74
-
75
- try {
76
- await this.initMaster(as);
77
- this._currentAs = as;
78
- await func(this);
79
- this._currentAs = this._defaultAs;
80
- } catch (e) {
81
- throw e;
82
- }
83
- }
84
- async nextTx(as, func) {
85
- return this.next_tx(as, func);
86
- }
87
-
88
- take_from_sender(typeName) {
89
- const asAsAddress = this._masters[this._currentAs].address;
90
- const objectStorage = this._masters[this._currentAs].objectStorage; // it's same object for different 'as' connected to the same provider, but we don't care here
91
- return objectStorage.findMostRecent((object)=>{
92
- return (object.typeName == typeName && object.isOwnedBy(asAsAddress));
93
- });
94
- }
95
- takeFromSender(typeName) {
96
- return this.take_from_sender(typeName);
97
- }
98
-
99
- take_shared(typeName) {
100
- const objectStorage = this._masters[this._currentAs].objectStorage; // it's same object for different 'as' connected to the same provider, but we don't care here
101
- return objectStorage.findMostRecent((object)=>{
102
- return (object.isShared && object.typeName == typeName);
103
- });
104
- }
105
- takeShared(typeName) {
106
- return this.take_shared(typeName);
107
- }
108
-
109
- take_immutable(typeName) {
110
- const objectStorage = this._masters[this._currentAs].objectStorage; // it's same object for different 'as' connected to the same provider, but we don't care here
111
- return objectStorage.findMostRecent((object)=>{
112
- return (object.isImmutable && object.typeName == typeName);
113
- });
114
- }
115
- takeImmutable(typeName) {
116
- return this.take_immutable(typeName);
117
- }
118
-
119
- async moveCall(moduleName, methodName, params) {
120
- if (!this._currentAs) {
121
- throw new Error('please call moveCall inside .next_tx(as, ()=>{}) wrapper');
122
- }
123
-
124
- await this._packages[this._currentAs].modules[moduleName].moveCall(methodName, params);
125
- }
126
-
127
- async initMaster(as) {
128
- if (this._masters[as]) {
129
- return true;
130
- }
131
-
132
- const suiMaster = new SuiMaster({debug: this._debug, as: as, client: this._client, });
133
-
134
- await suiMaster.initialize();
135
- await suiMaster.requestSuiFromFaucet();
136
-
137
- const addPackageParams = {};
138
- if (this._publishedPackageId) {
139
- // already pulished
140
- addPackageParams.id = this._publishedPackageId;
141
- } else {
142
- // to be build and published
143
- addPackageParams.path = this._path;
144
- }
145
- const addedPackage = suiMaster.addPackage(addPackageParams);
146
- // addedPackage.addEventListener('added', (data)=>{
147
- // const object = data.detail;
148
- // if (object && !this._objects[object.address]) { // there may be few same object instances in different suiMaster's.
149
- // this._objects[object.address] = object;
150
- // }
151
- // });
152
-
153
- if (!this._publishedPackageId) {
154
- await addedPackage.publish();
155
- this._publishedPackageId = addedPackage.id;
156
-
157
- if (!this._publishedPackageId) {
158
- this.log('can not publish a package');
159
- }
160
- } else {
161
- await addedPackage.isOnChain(); // check modules etc for other user
162
- }
163
-
164
-
165
- this._masters[as] = suiMaster;
166
- this._packages[as] = addedPackage;
167
- }
168
-
169
- };
@@ -1,61 +0,0 @@
1
- 'use strict'
2
-
3
- import t from 'tap';
4
- import { SuiTestScenario } 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 testScenario = null;
14
-
15
- test('initialization', async t => {
16
- testScenario = new SuiTestScenario({
17
- path: path.join(__dirname, './test_move_contracts/suidouble_chat/'),
18
- debug: false,
19
- });
20
-
21
- await testScenario.begin('admin');
22
- await testScenario.init();
23
-
24
- t.equal(testScenario.currentAs, 'admin');
25
- });
26
-
27
- test('checking takeShared', async t => {
28
- t.plan(4);
29
-
30
- await testScenario.nextTx('admin', async()=>{
31
- const chatShop = testScenario.takeShared('ChatShop');
32
-
33
- t.ok(chatShop.address); // there should be some address
34
- t.ok(`${chatShop.address}`.indexOf('0x') === 0); // adress is string starting with '0x'
35
-
36
- await testScenario.moveCall('suidouble_chat', 'post', [chatShop.address, testScenario.arg('string', 'posting a message'), testScenario.arg('string', 'metadata')]);
37
- const chatTopMessage = testScenario.takeShared('ChatTopMessage');
38
-
39
- t.ok(chatTopMessage.address); // there should be some address
40
- t.ok(`${chatTopMessage.address}`.indexOf('0x') === 0); // adress is string starting with '0x'
41
- });
42
- });
43
-
44
- test('checking takeOwned', async t => {
45
- t.plan(3);
46
-
47
- await testScenario.nextTx('somebody', async()=>{
48
- const chatTopMessage = testScenario.takeShared('ChatTopMessage');
49
- t.ok(chatTopMessage.address); // there should be some address
50
-
51
- await testScenario.moveCall('suidouble_chat', 'reply', [chatTopMessage.address, testScenario.arg('string', 'posting a response'), testScenario.arg('string', 'metadata')]);
52
- const chatResponse = testScenario.takeFromSender('ChatResponse');
53
-
54
- t.ok(chatResponse.address); // there should be some address
55
- t.ok(`${chatResponse.address}`.indexOf('0x') === 0); // adress is string starting with '0x'
56
- });
57
- })
58
-
59
- test('finishing the test scenario', async t => {
60
- await testScenario.end();
61
- });