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.
- package/.claude/settings.local.json +7 -0
- package/README.md +222 -131
- package/index.js +1 -3
- package/lib/SuiCliCommands.js +18 -25
- package/lib/SuiCoin.js +86 -138
- package/lib/SuiCoins.js +70 -31
- package/lib/SuiCommonMethods.js +40 -3
- package/lib/SuiEvent.js +54 -6
- package/lib/SuiInBrowser.js +145 -46
- package/lib/SuiInBrowserAdapter.js +164 -37
- package/lib/SuiLocalTestValidator.js +78 -25
- package/lib/SuiMaster.js +351 -126
- package/lib/SuiMemoryObjectStorage.js +66 -73
- package/lib/SuiObject.js +128 -153
- package/lib/SuiPackage.js +292 -187
- package/lib/SuiPackageModule.js +176 -221
- package/lib/SuiPaginatedResponse.js +288 -25
- package/lib/SuiPseudoRandomAddress.js +29 -2
- package/lib/SuiTransaction.js +115 -70
- package/lib/SuiUtils.js +179 -124
- package/package.json +30 -14
- package/test/build_modules.test.js +41 -0
- package/test/coins.test.js +17 -16
- package/test/custom_transaction.test.js +167 -0
- package/test/event_listeners.test.js +171 -0
- package/test/failed_transaction.test.js +184 -0
- package/test/name_service.test.js +28 -0
- package/test/owned_objects.test.js +148 -0
- package/test/rpc.test.js +3 -6
- package/test/sui_in_browser.test.js +2 -2
- package/test/sui_master_basic.test.js +4 -5
- package/test/sui_master_onlocal.test.js +84 -22
- package/test/sui_object_properties.test.js +85 -0
- package/test/test_move_contracts/different_types/Move.lock +18 -21
- package/test/test_move_contracts/different_types/sources/different_types.move +12 -12
- package/test/test_move_contracts/suidouble_chat/Move.lock +18 -22
- package/test/test_move_contracts/suidouble_chat/sources/suidouble_chat.move +9 -8
- package/tsconfig.json +15 -0
- package/types/index.d.ts +15 -0
- package/types/lib/SuiCliCommands.d.ts +6 -0
- package/types/lib/SuiCoin.d.ts +183 -0
- package/types/lib/SuiCoins.d.ts +93 -0
- package/types/lib/SuiCommonMethods.d.ts +37 -0
- package/types/lib/SuiEvent.d.ts +95 -0
- package/types/lib/SuiInBrowser.d.ts +189 -0
- package/types/lib/SuiInBrowserAdapter.d.ts +167 -0
- package/types/lib/SuiLocalTestValidator.d.ts +92 -0
- package/types/lib/SuiMaster.d.ts +333 -0
- package/types/lib/SuiMemoryObjectStorage.d.ts +96 -0
- package/types/lib/SuiObject.d.ts +135 -0
- package/types/lib/SuiPackage.d.ts +233 -0
- package/types/lib/SuiPackageModule.d.ts +139 -0
- package/types/lib/SuiPaginatedResponse.d.ts +148 -0
- package/types/lib/SuiPseudoRandomAddress.d.ts +33 -0
- package/types/lib/SuiTransaction.d.ts +92 -0
- package/types/lib/SuiUtils.d.ts +152 -0
- package/types/lib/data/icons.d.ts +12 -0
- package/lib/SuiTestScenario.js +0 -169
- package/test/sui_test_scenario.test.js +0 -61
package/lib/SuiCommonMethods.js
CHANGED
|
@@ -1,37 +1,74 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Minimal `CustomEvent` polyfill — `globalThis.CustomEvent` is not universally available
|
|
3
|
+
* in Node runtimes, so suidouble dispatches its own class with a `detail` field.
|
|
4
|
+
*/
|
|
3
5
|
class CustomEvent extends Event {
|
|
4
6
|
#detail;
|
|
5
7
|
|
|
8
|
+
/**
|
|
9
|
+
* @param {string} type
|
|
10
|
+
* @param {EventInit & { detail?: * }} [options]
|
|
11
|
+
*/
|
|
6
12
|
constructor(type, options) {
|
|
7
13
|
super(type, options);
|
|
8
14
|
this.#detail = options?.detail ?? null;
|
|
9
15
|
}
|
|
10
16
|
|
|
17
|
+
/** @returns {*} the payload passed via `options.detail` at construction time, or null */
|
|
11
18
|
get detail() {
|
|
12
19
|
return this.#detail;
|
|
13
20
|
}
|
|
14
21
|
}
|
|
15
22
|
|
|
23
|
+
/**
|
|
24
|
+
* Base class for suidouble domain objects. Extends `EventTarget` so subclasses can emit
|
|
25
|
+
* events via `this.emit(...)` and consumers can subscribe via `addEventListener(...)`.
|
|
26
|
+
* Also provides a debug-gated `log(...)` helper.
|
|
27
|
+
*/
|
|
16
28
|
export default class SuiCommonMethods extends EventTarget {
|
|
29
|
+
/**
|
|
30
|
+
* @param {Object} [params]
|
|
31
|
+
* @param {boolean} [params.debug] - enable debug logging via `log(...)`
|
|
32
|
+
*/
|
|
17
33
|
constructor(params = {}) {
|
|
18
34
|
super();
|
|
19
35
|
|
|
20
36
|
this._debug = !!params.debug;
|
|
21
37
|
}
|
|
22
38
|
|
|
39
|
+
/**
|
|
40
|
+
* Debug logger. No-op unless the instance was constructed with `debug: true`.
|
|
41
|
+
* Prefixes messages with the owning SuiMaster's instance number (if available) and the class name.
|
|
42
|
+
* @param {...any} args
|
|
43
|
+
*/
|
|
23
44
|
log(...args) {
|
|
24
45
|
if (!this._debug) {
|
|
25
46
|
return;
|
|
26
47
|
}
|
|
27
48
|
|
|
28
|
-
|
|
49
|
+
const self = /** @type {any} */ (this);
|
|
50
|
+
let prefix = (self._suiMaster ? (''+self._suiMaster.instanceN+' |') : (self.instanceN ? ''+self.instanceN+' |' : '') );
|
|
29
51
|
|
|
30
52
|
args.unshift(this.constructor.name+' |');
|
|
31
53
|
args.unshift(prefix);
|
|
32
54
|
console.info.apply(null, args);
|
|
33
55
|
}
|
|
34
56
|
|
|
57
|
+
/**
|
|
58
|
+
* Dispatch an event to registered `addEventListener` subscribers.
|
|
59
|
+
*
|
|
60
|
+
* If `data` is a `SuiEvent` (has `isSuiEvent === true`) and `forceCustom` is falsy, it is dispatched
|
|
61
|
+
* directly so its own `.type` (the Move event name) is used — this lets consumers
|
|
62
|
+
* `addEventListener('ChatShopCreated', …)` without wrapping. Otherwise dispatches a `CustomEvent`
|
|
63
|
+
* of type `eventType` with `data` placed on the event's `detail` field.
|
|
64
|
+
*
|
|
65
|
+
* Any dispatch errors are caught and logged to `console.error` so a buggy listener can't abort the
|
|
66
|
+
* surrounding flow.
|
|
67
|
+
*
|
|
68
|
+
* @param {string} eventType - event name when wrapping in a CustomEvent (ignored for direct SuiEvent dispatch)
|
|
69
|
+
* @param {*} data - payload; SuiEvent is dispatched directly, anything else is wrapped
|
|
70
|
+
* @param {boolean} [forceCustom=false] - if true, always wrap in a CustomEvent even for SuiEvent payloads
|
|
71
|
+
*/
|
|
35
72
|
emit(eventType, data, forceCustom = false) {
|
|
36
73
|
try {
|
|
37
74
|
if (data && data.isSuiEvent && !forceCustom) {
|
package/lib/SuiEvent.js
CHANGED
|
@@ -1,27 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {import("./SuiMaster.js").default} SuiMaster
|
|
3
|
+
*
|
|
4
|
+
* @typedef SuiEventData
|
|
5
|
+
* @type {object}
|
|
6
|
+
* @property {string} [type] - Fully-qualified Move type of the event, e.g. `<pkg>::<module>::<EventName>`
|
|
7
|
+
* @property {Object} [parsedJson] - JSON representation of the event's Move struct contents
|
|
8
|
+
* @property {string|number} [timestampMs] - Timestamp (ms since epoch) of the checkpoint the event's tx was finalized in
|
|
9
|
+
* @property {string} [sender] - SuiAddress of the sender of the emitting transaction
|
|
10
|
+
* @property {string} [transactionDigest] - Digest of the emitting transaction
|
|
11
|
+
* @property {string|number} [sequenceNumber] - Event position within its transaction
|
|
12
|
+
* @property {string|Uint8Array} [bcs] - BCS bytes (base64 string from GraphQL, Uint8Array from gRPC)
|
|
13
|
+
*/
|
|
1
14
|
|
|
2
|
-
|
|
15
|
+
/**
|
|
16
|
+
* Wrapper over a Sui event. Extends the native `Event` so it can be dispatched through
|
|
17
|
+
* `EventTarget`-style listeners; also exposes the common Sui event fields directly.
|
|
18
|
+
*/
|
|
3
19
|
export default class SuiEvent extends Event {
|
|
4
|
-
|
|
20
|
+
/**
|
|
21
|
+
* @param {Object} params - Initialization parameters
|
|
22
|
+
* @param {SuiMaster} params.suiMaster - instance of SuiMaster
|
|
23
|
+
* @param {SuiEventData} [params.data] - raw event data
|
|
24
|
+
* @param {boolean} [params.debug] - enable debug logging
|
|
25
|
+
*/
|
|
26
|
+
constructor(params) {
|
|
5
27
|
const typeName = params.data ? ((''+params.data.type).split('<')[0].split('::').pop()) : null;
|
|
6
28
|
super(typeName, {});
|
|
7
29
|
|
|
8
30
|
this._debug = !!params.debug;
|
|
31
|
+
/** @type {SuiMaster} */
|
|
9
32
|
this._suiMaster = params.suiMaster;
|
|
10
33
|
if (!this._suiMaster) {
|
|
11
|
-
throw new Error('suiMaster is
|
|
34
|
+
throw new Error('suiMaster is required for SuiEvent');
|
|
12
35
|
}
|
|
13
36
|
|
|
37
|
+
/** @type {SuiEventData} */
|
|
14
38
|
this._data = params.data || {};
|
|
15
39
|
|
|
16
40
|
this.detail = this; // quick backward support as this is the instance of CustomEvent
|
|
17
41
|
}
|
|
18
42
|
|
|
43
|
+
/**
|
|
44
|
+
* Debug logger. No-op unless the instance was constructed with `debug: true`.
|
|
45
|
+
* Prefixes messages with the SuiMaster instance number and the class name.
|
|
46
|
+
* @param {...any} args
|
|
47
|
+
*/
|
|
19
48
|
log(...args) {
|
|
20
49
|
if (!this._debug) {
|
|
21
50
|
return;
|
|
22
51
|
}
|
|
23
52
|
|
|
24
|
-
|
|
53
|
+
const self = /** @type {any} */ (this);
|
|
54
|
+
let prefix = (self._suiMaster ? (''+self._suiMaster.instanceN+' |') : (self.instanceN ? ''+self.instanceN+' |' : '') );
|
|
25
55
|
// prefix += this.constructor.name+' | ';
|
|
26
56
|
|
|
27
57
|
args.unshift(this.constructor.name+' |');
|
|
@@ -29,25 +59,39 @@ export default class SuiEvent extends Event {
|
|
|
29
59
|
console.info.apply(null, args);
|
|
30
60
|
}
|
|
31
61
|
|
|
62
|
+
/** Brand property for duck-typing. @returns {true} */
|
|
32
63
|
get isSuiEvent() {
|
|
33
64
|
return true;
|
|
34
65
|
}
|
|
35
66
|
|
|
36
67
|
/**
|
|
37
|
-
* In
|
|
68
|
+
* In-module type name — last segment of `package::module::Name<...>`, without package/module prefix or `<T..>` suffix.
|
|
69
|
+
* @returns {?string}
|
|
38
70
|
*/
|
|
39
71
|
get typeName() {
|
|
40
72
|
return this._data ? (''+this._data.type).split('<')[0].split('::').pop() : null;
|
|
41
73
|
}
|
|
42
74
|
|
|
75
|
+
/**
|
|
76
|
+
* Fully-qualified Move type of the event, e.g. `<pkg>::<module>::<EventName>[<type-params>]`.
|
|
77
|
+
* @returns {?string}
|
|
78
|
+
*/
|
|
43
79
|
get type() {
|
|
44
80
|
return this._data ? (''+this._data.type) : null;
|
|
45
81
|
}
|
|
46
82
|
|
|
83
|
+
/**
|
|
84
|
+
* Raw event data as received from the client.
|
|
85
|
+
* @returns {SuiEventData}
|
|
86
|
+
*/
|
|
47
87
|
get data() {
|
|
48
88
|
return this._data;
|
|
49
89
|
}
|
|
50
90
|
|
|
91
|
+
/**
|
|
92
|
+
* JSON representation of the event's Move struct contents.
|
|
93
|
+
* @returns {?Object}
|
|
94
|
+
*/
|
|
51
95
|
get parsedJson() {
|
|
52
96
|
if (this._data.parsedJson) {
|
|
53
97
|
return this._data.parsedJson;
|
|
@@ -55,9 +99,13 @@ export default class SuiEvent extends Event {
|
|
|
55
99
|
return null;
|
|
56
100
|
}
|
|
57
101
|
|
|
102
|
+
/**
|
|
103
|
+
* Timestamp (milliseconds since epoch) of the checkpoint the emitting transaction was finalized in.
|
|
104
|
+
* @returns {?number}
|
|
105
|
+
*/
|
|
58
106
|
get timestampMs() {
|
|
59
107
|
if (this._data.timestampMs) {
|
|
60
|
-
return parseInt(this._data.timestampMs, 10);
|
|
108
|
+
return parseInt('' + this._data.timestampMs, 10);
|
|
61
109
|
} else {
|
|
62
110
|
return null;
|
|
63
111
|
}
|
package/lib/SuiInBrowser.js
CHANGED
|
@@ -1,30 +1,63 @@
|
|
|
1
1
|
import SuiCommonMethods from './SuiCommonMethods.js';
|
|
2
2
|
import SuiInBrowserAdapter from './SuiInBrowserAdapter.js';
|
|
3
3
|
import { getWallets } from '@wallet-standard/core';
|
|
4
|
-
import { SuiClient } from '@mysten/sui/client';
|
|
5
4
|
import SuiMaster from './SuiMaster.js';
|
|
5
|
+
import { toBase64 } from '@mysten/bcs';
|
|
6
6
|
|
|
7
7
|
import icons from './data/icons.js';
|
|
8
8
|
|
|
9
|
+
/**
|
|
10
|
+
* @typedef {import("@mysten/sui/grpc").SuiGrpcClient} SuiGrpcClient
|
|
11
|
+
* @typedef {import("@mysten/sui/cryptography").SignatureWithBytes} SignatureWithBytes
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
|
|
9
15
|
const DEFAULT_CHAIN = 'sui:devnet';
|
|
10
16
|
|
|
17
|
+
/**
|
|
18
|
+
* Browser-side entry point for wallet integration. Manages a registry of SuiInBrowserAdapter
|
|
19
|
+
* instances (one per known wallet), tracks the active connection, and creates a SuiMaster
|
|
20
|
+
* pointing at the connected chain.
|
|
21
|
+
*
|
|
22
|
+
* Starts initialising itself 50 ms after construction so callers have time to attach listeners.
|
|
23
|
+
* Use SuiInBrowser.getSingleton({ defaultChain }) for the typical single-page-app pattern.
|
|
24
|
+
*
|
|
25
|
+
* Events emitted:
|
|
26
|
+
* - 'adapter' — a new SuiInBrowserAdapter was registered (detail: adapter)
|
|
27
|
+
* - 'connected' — the active adapter connected
|
|
28
|
+
* - 'disconnected' — the active adapter disconnected
|
|
29
|
+
* - 'rpc' — the RPC endpoint was changed via setRPC
|
|
30
|
+
*/
|
|
11
31
|
export default class SuiInBrowser extends SuiCommonMethods {
|
|
32
|
+
/**
|
|
33
|
+
* @param {Object} [params]
|
|
34
|
+
* @param {string} [params.defaultChain='sui:devnet'] - chain used before any wallet connects
|
|
35
|
+
* @param {boolean} [params.debug]
|
|
36
|
+
*/
|
|
12
37
|
constructor(params = {}) {
|
|
13
38
|
super(params);
|
|
14
39
|
|
|
40
|
+
/** @type {Object.<string, SuiInBrowserAdapter>} */
|
|
15
41
|
this._adapters = {};
|
|
16
42
|
|
|
43
|
+
/** @type {string} */
|
|
17
44
|
this._defaultChain = params.defaultChain || DEFAULT_CHAIN;
|
|
18
45
|
|
|
46
|
+
/** @type {?SuiInBrowserAdapter} */
|
|
19
47
|
this._activeAdapter = null;
|
|
48
|
+
/** @type {?string} */
|
|
20
49
|
this._connectedAddress = null;
|
|
50
|
+
/** @type {?string} */
|
|
21
51
|
this._connectedChain = null;
|
|
52
|
+
/** @type {boolean} */
|
|
22
53
|
this._isConnected = false;
|
|
54
|
+
/** @type {boolean} */
|
|
23
55
|
this._isConnecting = false;
|
|
24
56
|
|
|
25
57
|
this._client = null;
|
|
26
58
|
this._suiMaster = null;
|
|
27
59
|
|
|
60
|
+
/** @type {?Object} */
|
|
28
61
|
this._rpcSettings = null;
|
|
29
62
|
|
|
30
63
|
setTimeout(()=>{
|
|
@@ -32,53 +65,103 @@ export default class SuiInBrowser extends SuiCommonMethods {
|
|
|
32
65
|
}, 50);
|
|
33
66
|
}
|
|
34
67
|
|
|
68
|
+
/** @returns {?SuiInBrowserAdapter} The currently active wallet adapter, or null. */
|
|
35
69
|
get activeAdapter() {
|
|
36
70
|
return this._activeAdapter;
|
|
37
71
|
}
|
|
38
72
|
|
|
73
|
+
/**
|
|
74
|
+
* Returns the currently connected wallet address, or null if not connected.
|
|
75
|
+
* @returns {?string}
|
|
76
|
+
*/
|
|
39
77
|
getAddress() {
|
|
40
78
|
return this._connectedAddress;
|
|
41
79
|
}
|
|
42
80
|
|
|
81
|
+
/**
|
|
82
|
+
* Sign a transaction using the current `sui:signTransaction` feature.
|
|
83
|
+
* @param {Object} params
|
|
84
|
+
* @returns {Promise<SignatureWithBytes>}
|
|
85
|
+
*/
|
|
86
|
+
async signTransaction(params) {
|
|
87
|
+
const enriched = { account: { address: this._connectedAddress }, chain: this._connectedChain, ...params };
|
|
88
|
+
return await this._activeAdapter.signTransaction(enriched);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Delegates to the active adapter using the legacy transaction-block API.
|
|
93
|
+
* @param {Object} params
|
|
94
|
+
* @returns {Promise<*>}
|
|
95
|
+
*/
|
|
43
96
|
async signAndExecuteTransactionBlock(params) {
|
|
44
97
|
return await this._activeAdapter.signAndExecuteTransactionBlock(params);
|
|
45
98
|
}
|
|
46
99
|
|
|
100
|
+
/**
|
|
101
|
+
* Delegates to the active adapter using the current transaction API.
|
|
102
|
+
* @param {Object} params
|
|
103
|
+
* @returns {Promise<*>}
|
|
104
|
+
*/
|
|
47
105
|
async signAndExecuteTransaction(params) {
|
|
48
|
-
|
|
106
|
+
const enriched = { account: { address: this._connectedAddress }, chain: this._connectedChain, ...params };
|
|
107
|
+
return await this._activeAdapter.signAndExecuteTransaction(enriched);
|
|
49
108
|
}
|
|
50
109
|
|
|
110
|
+
/** @returns {*} The gRPC client instance, or null if not yet initialised. */
|
|
51
111
|
get client() {
|
|
52
112
|
return this._client;
|
|
53
113
|
}
|
|
54
114
|
|
|
115
|
+
toSuiAddress() {
|
|
116
|
+
return this._connectedAddress;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Ensures the client is initialised, then returns it.
|
|
121
|
+
* @returns {Promise<*>}
|
|
122
|
+
*/
|
|
55
123
|
async getClient() {
|
|
56
124
|
await this.initClient();
|
|
57
125
|
return this._client;
|
|
58
126
|
}
|
|
59
127
|
|
|
128
|
+
/**
|
|
129
|
+
* Ensures the client is initialised, then returns the SuiMaster instance.
|
|
130
|
+
* @returns {Promise<SuiMaster>}
|
|
131
|
+
*/
|
|
60
132
|
async getSuiMaster() {
|
|
61
133
|
await this.initClient();
|
|
62
134
|
return this._suiMaster;
|
|
63
135
|
}
|
|
64
136
|
|
|
137
|
+
/** @returns {?SuiMaster} The current SuiMaster instance, or null if not yet initialised. */
|
|
65
138
|
get suiMaster() {
|
|
66
139
|
return this._suiMaster;
|
|
67
140
|
}
|
|
68
141
|
|
|
142
|
+
/** @returns {boolean} True if a wallet adapter is currently connected. */
|
|
69
143
|
get isConnected() {
|
|
70
144
|
return this._isConnected;
|
|
71
145
|
}
|
|
72
146
|
|
|
147
|
+
/** @returns {?string} The active wallet address, or null if not connected. */
|
|
73
148
|
get connectedAddress() {
|
|
74
149
|
return this._connectedAddress;
|
|
75
150
|
}
|
|
76
151
|
|
|
152
|
+
/** @returns {?string} The chain the active adapter is connected to (e.g. 'sui:mainnet'), or null. */
|
|
77
153
|
get connectedChain() {
|
|
78
154
|
return this._connectedChain;
|
|
79
155
|
}
|
|
80
156
|
|
|
81
157
|
static _singleInstances = {};
|
|
158
|
+
/**
|
|
159
|
+
* Returns the singleton SuiInBrowser instance for the given defaultChain, creating it if
|
|
160
|
+
* necessary. Ideal for single-page-app usage where one instance is shared across the app.
|
|
161
|
+
* @param {Object} [params]
|
|
162
|
+
* @param {string} [params.defaultChain]
|
|
163
|
+
* @returns {SuiInBrowser}
|
|
164
|
+
*/
|
|
82
165
|
static getSingleton(params = {}) {
|
|
83
166
|
let defaultChainKey = params.defaultChain || DEFAULT_CHAIN;
|
|
84
167
|
|
|
@@ -90,15 +173,20 @@ export default class SuiInBrowser extends SuiCommonMethods {
|
|
|
90
173
|
return SuiInBrowser._singleInstances[defaultChainKey];
|
|
91
174
|
}
|
|
92
175
|
|
|
176
|
+
/** @returns {Object.<string, SuiInBrowserAdapter>} Map of adapter name to SuiInBrowserAdapter. */
|
|
93
177
|
get adapters() {
|
|
94
178
|
return this._adapters;
|
|
95
179
|
}
|
|
96
180
|
|
|
181
|
+
/**
|
|
182
|
+
* Connects to a named adapter or an adapter instance. Returns false if the adapter is not
|
|
183
|
+
* found in the registry.
|
|
184
|
+
* @param {string|SuiInBrowserAdapter} adapterOrAdapterName
|
|
185
|
+
* @returns {Promise<boolean|void>}
|
|
186
|
+
*/
|
|
97
187
|
async connect(adapterOrAdapterName) {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
adapterName = adapterOrAdapterName.name;
|
|
101
|
-
}
|
|
188
|
+
const a = /** @type {any} */ (adapterOrAdapterName);
|
|
189
|
+
const adapterName = a.name ?? a;
|
|
102
190
|
|
|
103
191
|
if (!this._adapters[adapterName]) {
|
|
104
192
|
return false;
|
|
@@ -114,11 +202,15 @@ export default class SuiInBrowser extends SuiCommonMethods {
|
|
|
114
202
|
this._isConnecting = false;
|
|
115
203
|
}
|
|
116
204
|
|
|
205
|
+
/**
|
|
206
|
+
* Called when an adapter fires its 'connected' event. Updates the active adapter, connected
|
|
207
|
+
* address and chain, rebuilds the gRPC client and SuiMaster, and emits 'connected'.
|
|
208
|
+
* @param {SuiInBrowserAdapter} suiInBrowserAdapter
|
|
209
|
+
*/
|
|
117
210
|
adapterConnected(suiInBrowserAdapter) {
|
|
118
211
|
this._activeAdapter = suiInBrowserAdapter;
|
|
119
212
|
this._isConnected = suiInBrowserAdapter.isConnected;
|
|
120
213
|
this._connectedAddress = suiInBrowserAdapter.connectedAddress;
|
|
121
|
-
const wasConnectedToChain = this._connectedChain;
|
|
122
214
|
this._connectedChain = suiInBrowserAdapter.connectedChain;
|
|
123
215
|
|
|
124
216
|
if (this._connectedChain == 'sui:unknown') {
|
|
@@ -128,9 +220,9 @@ export default class SuiInBrowser extends SuiCommonMethods {
|
|
|
128
220
|
this._client = null;
|
|
129
221
|
this._suiMaster = null;
|
|
130
222
|
|
|
131
|
-
this.initClient()
|
|
132
|
-
|
|
133
|
-
|
|
223
|
+
this.initClient().then(() => {
|
|
224
|
+
this.emit('connected');
|
|
225
|
+
});
|
|
134
226
|
}
|
|
135
227
|
|
|
136
228
|
/**
|
|
@@ -140,7 +232,7 @@ export default class SuiInBrowser extends SuiCommonMethods {
|
|
|
140
232
|
* @param {Object} params.rpc rpc settings
|
|
141
233
|
* @param {Object.<string, string>} params.rpc.headers rpc headers
|
|
142
234
|
*/
|
|
143
|
-
async setRPC(params
|
|
235
|
+
async setRPC(params) {
|
|
144
236
|
this._rpcSettings = params;
|
|
145
237
|
this._client = null;
|
|
146
238
|
this._suiMaster = null;
|
|
@@ -150,13 +242,29 @@ export default class SuiInBrowser extends SuiCommonMethods {
|
|
|
150
242
|
this.emit('rpc');
|
|
151
243
|
}
|
|
152
244
|
|
|
153
|
-
|
|
245
|
+
/**
|
|
246
|
+
* Called when an adapter fires its 'disconnected' event. Resets connection state and emits
|
|
247
|
+
* 'disconnected'.
|
|
248
|
+
* @param {SuiInBrowserAdapter} [_suiInBrowserAdapter]
|
|
249
|
+
*/
|
|
250
|
+
adapterDisconnected(_suiInBrowserAdapter) {
|
|
154
251
|
this._isConnected = false;
|
|
155
252
|
this._connectedAddress = null;
|
|
156
253
|
|
|
157
254
|
this.emit('disconnected');
|
|
158
255
|
}
|
|
159
256
|
|
|
257
|
+
/**
|
|
258
|
+
* Registers a wallet adapter in the registry. If the adapter is new, creates a
|
|
259
|
+
* SuiInBrowserAdapter instance, wires up its events, and emits 'adapter'. If the adapter
|
|
260
|
+
* already exists and a standartAdapter is provided, updates it instead.
|
|
261
|
+
* @param {Object} adapterParams
|
|
262
|
+
* @param {string} [adapterParams.name]
|
|
263
|
+
* @param {Object} [adapterParams.standartAdapter]
|
|
264
|
+
* @param {string} [adapterParams.icon]
|
|
265
|
+
* @param {Object} [adapterParams.downloadUrls]
|
|
266
|
+
* @returns {void|false}
|
|
267
|
+
*/
|
|
160
268
|
attachAdapter(adapterParams) {
|
|
161
269
|
let adapterName = adapterParams.name;
|
|
162
270
|
if (adapterParams.standartAdapter && adapterParams.standartAdapter.name) {
|
|
@@ -179,37 +287,43 @@ export default class SuiInBrowser extends SuiCommonMethods {
|
|
|
179
287
|
} else {
|
|
180
288
|
this._adapters[adapterName] = adapter;
|
|
181
289
|
this._adapters[adapterName].addEventListener('connected', (e)=>{
|
|
182
|
-
this.adapterConnected(e.detail);
|
|
290
|
+
this.adapterConnected(/** @type {any} */ (e).detail);
|
|
183
291
|
});
|
|
184
292
|
this._adapters[adapterName].addEventListener('disconnected', (e)=>{
|
|
185
|
-
this.adapterDisconnected(e.detail);
|
|
293
|
+
this.adapterDisconnected(/** @type {any} */ (e).detail);
|
|
186
294
|
});
|
|
187
295
|
this.emit('adapter', adapter);
|
|
188
296
|
}
|
|
189
297
|
}
|
|
190
298
|
|
|
299
|
+
/**
|
|
300
|
+
* Returns the currently connected chain, or the default chain if no wallet is connected.
|
|
301
|
+
* @returns {string}
|
|
302
|
+
*/
|
|
191
303
|
getCurrentChain() {
|
|
192
304
|
return this._connectedChain ? this._connectedChain : this._defaultChain;
|
|
193
305
|
}
|
|
194
306
|
|
|
307
|
+
/**
|
|
308
|
+
* Builds the gRPC client and SuiMaster for the current chain. No-op if already built.
|
|
309
|
+
* Uses _rpcSettings when a custom RPC endpoint has been set via setRPC.
|
|
310
|
+
* @returns {Promise<void>}
|
|
311
|
+
*/
|
|
195
312
|
async initClient() {
|
|
196
313
|
if (this._client) {
|
|
197
|
-
return
|
|
314
|
+
return;
|
|
198
315
|
}
|
|
199
316
|
|
|
200
317
|
let chainName = this.getCurrentChain();
|
|
201
|
-
const chainSettings = SuiInBrowser.getChainsSettings();
|
|
202
|
-
// https://github.com/MystenLabs/sui/blob/827f1138a09190975172ec99389751ca95cce5df/sdk/typescript/src/rpc/connection.ts#L32
|
|
203
318
|
|
|
204
319
|
if (this._rpcSettings) {
|
|
205
320
|
this._rpcSettings.providerName = chainName.split('sui:').join('');
|
|
206
|
-
this._client = SuiMaster.SuiUtils.suiClientForRPC(this._rpcSettings);
|
|
207
|
-
} else if (!
|
|
321
|
+
this._client = SuiMaster.SuiUtils.suiClientForRPC(this._rpcSettings.providerName ?? chainName, this._rpcSettings);
|
|
322
|
+
} else if (!chainName) {
|
|
208
323
|
this.log('error', 'invalid chain', chainName);
|
|
209
324
|
throw new Error('invalid chain: '+chainName);
|
|
210
325
|
} else {
|
|
211
|
-
this._client =
|
|
212
|
-
this._client.endpoint = chainSettings[chainName].fullnode;
|
|
326
|
+
this._client = SuiMaster.SuiUtils.suiClientFor(chainName);
|
|
213
327
|
}
|
|
214
328
|
|
|
215
329
|
this._suiMaster = new SuiMaster({
|
|
@@ -219,6 +333,11 @@ export default class SuiInBrowser extends SuiCommonMethods {
|
|
|
219
333
|
});
|
|
220
334
|
}
|
|
221
335
|
|
|
336
|
+
/**
|
|
337
|
+
* Seeds the adapter registry from the known-wallets list and the live Wallet Standard
|
|
338
|
+
* registry, then subscribes to future 'register' events for dynamically installed wallets.
|
|
339
|
+
* @returns {Promise<void>}
|
|
340
|
+
*/
|
|
222
341
|
async initialize() {
|
|
223
342
|
await this.initClient(); // set default client
|
|
224
343
|
|
|
@@ -245,31 +364,11 @@ export default class SuiInBrowser extends SuiCommonMethods {
|
|
|
245
364
|
});
|
|
246
365
|
}
|
|
247
366
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
faucet: 'https://faucet.devnet.sui.io/gas',
|
|
254
|
-
},
|
|
255
|
-
'sui:testnet': {
|
|
256
|
-
fullnode: 'https://fullnode.testnet.sui.io:443/',
|
|
257
|
-
websocket: 'https://fullnode.testnet.sui.io:443/',
|
|
258
|
-
faucet: 'https://faucet.testnet.sui.io/gas',
|
|
259
|
-
},
|
|
260
|
-
'sui:mainnet': {
|
|
261
|
-
fullnode: 'https://fullnode.mainnet.sui.io:443/',
|
|
262
|
-
websocket: 'https://fullnode.mainnet.sui.io:443/',
|
|
263
|
-
},
|
|
264
|
-
'sui:localnet': {
|
|
265
|
-
websocket: 'http://127.0.0.1:9000',
|
|
266
|
-
fullnode: 'http://127.0.0.1:9000',
|
|
267
|
-
websocket: 'http://127.0.0.1:9000',
|
|
268
|
-
faucet: 'http://127.0.0.1:9123/gas',
|
|
269
|
-
},
|
|
270
|
-
};
|
|
271
|
-
}
|
|
272
|
-
|
|
367
|
+
/**
|
|
368
|
+
* Returns the list of known wallet placeholder params used to pre-populate the adapter
|
|
369
|
+
* registry before the Wallet Standard registry is queried.
|
|
370
|
+
* @returns {Array<{name: string, icon: string, downloadUrls: Object}>}
|
|
371
|
+
*/
|
|
273
372
|
static getPossibleWallets() {
|
|
274
373
|
return [
|
|
275
374
|
{
|