@dynamic-labs/sui-core 4.48.0 → 4.48.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/CHANGELOG.md +7 -0
- package/package.cjs +1 -1
- package/package.js +1 -1
- package/package.json +8 -8
- package/src/SuiWalletConnector.cjs +60 -47
- package/src/SuiWalletConnector.d.ts +6 -2
- package/src/SuiWalletConnector.js +60 -47
- package/src/index.cjs +2 -0
- package/src/index.d.ts +1 -0
- package/src/index.js +1 -0
- package/src/wallets/injected/fetchSuiInjectedWalletConnectors.cjs +27 -2
- package/src/wallets/injected/fetchSuiInjectedWalletConnectors.js +27 -2
- package/src/wallets/slush/Slush.cjs +307 -0
- package/src/wallets/slush/Slush.d.ts +82 -0
- package/src/wallets/slush/Slush.js +303 -0
- package/src/wallets/slush/index.d.ts +1 -0
package/src/index.cjs
CHANGED
|
@@ -9,6 +9,7 @@ var constants = require('./utils/constants/constants.cjs');
|
|
|
9
9
|
var SuiWalletConnector = require('./SuiWalletConnector.cjs');
|
|
10
10
|
var SuiWallet = require('./wallet/SuiWallet.cjs');
|
|
11
11
|
var isSuiWallet = require('./wallet/isSuiWallet/isSuiWallet.cjs');
|
|
12
|
+
var Slush = require('./wallets/slush/Slush.cjs');
|
|
12
13
|
var SuiUiTransaction = require('./utils/SuiUiTransaction/SuiUiTransaction.cjs');
|
|
13
14
|
var fetchSuiInjectedWalletConnectors = require('./wallets/injected/fetchSuiInjectedWalletConnectors.cjs');
|
|
14
15
|
|
|
@@ -19,5 +20,6 @@ exports.MIST_PER_SUI = constants.MIST_PER_SUI;
|
|
|
19
20
|
exports.SuiWalletConnector = SuiWalletConnector.SuiWalletConnector;
|
|
20
21
|
exports.SuiWallet = SuiWallet.SuiWallet;
|
|
21
22
|
exports.isSuiWallet = isSuiWallet.isSuiWallet;
|
|
23
|
+
exports.Slush = Slush.Slush;
|
|
22
24
|
exports.SuiUiTransaction = SuiUiTransaction.SuiUiTransaction;
|
|
23
25
|
exports.fetchSuiInjectedWalletConnectors = fetchSuiInjectedWalletConnectors.fetchSuiInjectedWalletConnectors;
|
package/src/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ export * from './utils/constants';
|
|
|
2
2
|
export { SuiWalletConnector } from './SuiWalletConnector';
|
|
3
3
|
export { SuiWallet } from './wallet/SuiWallet';
|
|
4
4
|
export { isSuiWallet } from './wallet/isSuiWallet';
|
|
5
|
+
export { Slush } from './wallets/slush';
|
|
5
6
|
export type { SuiWalletConnectorProps, SuiSendBalanceProps } from './types';
|
|
6
7
|
export { SuiUiTransaction } from './utils/SuiUiTransaction/SuiUiTransaction';
|
|
7
8
|
export { fetchSuiInjectedWalletConnectors } from './wallets/injected/fetchSuiInjectedWalletConnectors';
|
package/src/index.js
CHANGED
|
@@ -5,6 +5,7 @@ export { MIST_PER_SUI } from './utils/constants/constants.js';
|
|
|
5
5
|
export { SuiWalletConnector } from './SuiWalletConnector.js';
|
|
6
6
|
export { SuiWallet } from './wallet/SuiWallet.js';
|
|
7
7
|
export { isSuiWallet } from './wallet/isSuiWallet/isSuiWallet.js';
|
|
8
|
+
export { Slush } from './wallets/slush/Slush.js';
|
|
8
9
|
export { SuiUiTransaction } from './utils/SuiUiTransaction/SuiUiTransaction.js';
|
|
9
10
|
export { fetchSuiInjectedWalletConnectors } from './wallets/injected/fetchSuiInjectedWalletConnectors.js';
|
|
10
11
|
|
|
@@ -6,22 +6,33 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
6
6
|
var walletStandard = require('@mysten/wallet-standard');
|
|
7
7
|
var utils = require('@dynamic-labs/utils');
|
|
8
8
|
var walletConnectorCore = require('@dynamic-labs/wallet-connector-core');
|
|
9
|
+
var Slush = require('../slush/Slush.cjs');
|
|
9
10
|
var injected = require('./injected.cjs');
|
|
10
11
|
|
|
12
|
+
// Wallets with custom connectors that should not be auto-generated
|
|
13
|
+
const walletsWithCustomConnectors = {
|
|
14
|
+
slush: Slush.Slush,
|
|
15
|
+
};
|
|
16
|
+
const getCustomConnectorForKey = (name) => {
|
|
17
|
+
var _a;
|
|
18
|
+
return (_a = Object.entries(walletsWithCustomConnectors).find(([key]) => name.toLowerCase().includes(key.toLowerCase()))) === null || _a === void 0 ? void 0 : _a[1];
|
|
19
|
+
};
|
|
11
20
|
const fetchSuiInjectedWalletConnectors = ({ walletBook, }) => {
|
|
12
21
|
var _a;
|
|
13
22
|
const walletStandardWallets = walletStandard.getWallets().get();
|
|
14
23
|
const suiWalletStandardWallets = walletStandardWallets.filter((wallet) => walletStandard.isWalletWithRequiredFeatureSet(wallet, ['sui:signPersonalMessage']));
|
|
15
24
|
const suiWalletsByKey = Object.fromEntries(suiWalletStandardWallets.map((wallet) => [wallet.name, wallet]));
|
|
16
25
|
const walletBookConnectors = Object.entries((_a = walletBook === null || walletBook === void 0 ? void 0 : walletBook.wallets) !== null && _a !== void 0 ? _a : {})
|
|
17
|
-
.filter(([, wallet]) => {
|
|
26
|
+
.filter(([key, wallet]) => {
|
|
18
27
|
var _a, _b;
|
|
19
28
|
const injectedConfig = (_a = wallet.injectedConfig) === null || _a === void 0 ? void 0 : _a.find((config) => config.chain === 'sui');
|
|
20
29
|
const isSuiWallet = Boolean(injectedConfig);
|
|
21
30
|
const walletStandardName = (_b = injectedConfig === null || injectedConfig === void 0 ? void 0 : injectedConfig.walletStandard) === null || _b === void 0 ? void 0 : _b.name;
|
|
22
31
|
// If the wallet is injected via wallet standard, use that over the wallet book entry
|
|
23
32
|
const shouldBeFiltered = walletStandardName && suiWalletsByKey[walletStandardName];
|
|
24
|
-
|
|
33
|
+
// Filter out wallets that have custom connectors
|
|
34
|
+
const hasCustomConnector = Boolean(getCustomConnectorForKey(key));
|
|
35
|
+
return isSuiWallet && !shouldBeFiltered && !hasCustomConnector;
|
|
25
36
|
})
|
|
26
37
|
.map(([key, wallet]) => {
|
|
27
38
|
// Currently we only support wallet standard wallets
|
|
@@ -44,7 +55,21 @@ const fetchSuiInjectedWalletConnectors = ({ walletBook, }) => {
|
|
|
44
55
|
.filter((wallet) => { var _a; return (_a = wallet.features) === null || _a === void 0 ? void 0 : _a['sui:signPersonalMessage']; })
|
|
45
56
|
.map((wallet) => {
|
|
46
57
|
const sanitizedName = utils.sanitizeName(wallet.name);
|
|
58
|
+
const customConnector = getCustomConnectorForKey(sanitizedName);
|
|
47
59
|
const isInstalled = true;
|
|
60
|
+
if (customConnector) {
|
|
61
|
+
return class extends customConnector {
|
|
62
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
63
|
+
constructor(props) {
|
|
64
|
+
super(wallet.name, isInstalled, Object.assign({ metadata: {
|
|
65
|
+
groupKey: sanitizedName,
|
|
66
|
+
icon: wallet.icon,
|
|
67
|
+
id: wallet.name,
|
|
68
|
+
name: wallet.name,
|
|
69
|
+
}, name: wallet.name, overrideKey: `${sanitizedName}sui`, wallet: wallet }, props));
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
}
|
|
48
73
|
return class extends injected.Injected {
|
|
49
74
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
50
75
|
constructor(props) {
|
|
@@ -2,22 +2,33 @@
|
|
|
2
2
|
import { getWallets, isWalletWithRequiredFeatureSet } from '@mysten/wallet-standard';
|
|
3
3
|
import { sanitizeName } from '@dynamic-labs/utils';
|
|
4
4
|
import { getWalletMetadataFromWalletBook } from '@dynamic-labs/wallet-connector-core';
|
|
5
|
+
import { Slush } from '../slush/Slush.js';
|
|
5
6
|
import { Injected } from './injected.js';
|
|
6
7
|
|
|
8
|
+
// Wallets with custom connectors that should not be auto-generated
|
|
9
|
+
const walletsWithCustomConnectors = {
|
|
10
|
+
slush: Slush,
|
|
11
|
+
};
|
|
12
|
+
const getCustomConnectorForKey = (name) => {
|
|
13
|
+
var _a;
|
|
14
|
+
return (_a = Object.entries(walletsWithCustomConnectors).find(([key]) => name.toLowerCase().includes(key.toLowerCase()))) === null || _a === void 0 ? void 0 : _a[1];
|
|
15
|
+
};
|
|
7
16
|
const fetchSuiInjectedWalletConnectors = ({ walletBook, }) => {
|
|
8
17
|
var _a;
|
|
9
18
|
const walletStandardWallets = getWallets().get();
|
|
10
19
|
const suiWalletStandardWallets = walletStandardWallets.filter((wallet) => isWalletWithRequiredFeatureSet(wallet, ['sui:signPersonalMessage']));
|
|
11
20
|
const suiWalletsByKey = Object.fromEntries(suiWalletStandardWallets.map((wallet) => [wallet.name, wallet]));
|
|
12
21
|
const walletBookConnectors = Object.entries((_a = walletBook === null || walletBook === void 0 ? void 0 : walletBook.wallets) !== null && _a !== void 0 ? _a : {})
|
|
13
|
-
.filter(([, wallet]) => {
|
|
22
|
+
.filter(([key, wallet]) => {
|
|
14
23
|
var _a, _b;
|
|
15
24
|
const injectedConfig = (_a = wallet.injectedConfig) === null || _a === void 0 ? void 0 : _a.find((config) => config.chain === 'sui');
|
|
16
25
|
const isSuiWallet = Boolean(injectedConfig);
|
|
17
26
|
const walletStandardName = (_b = injectedConfig === null || injectedConfig === void 0 ? void 0 : injectedConfig.walletStandard) === null || _b === void 0 ? void 0 : _b.name;
|
|
18
27
|
// If the wallet is injected via wallet standard, use that over the wallet book entry
|
|
19
28
|
const shouldBeFiltered = walletStandardName && suiWalletsByKey[walletStandardName];
|
|
20
|
-
|
|
29
|
+
// Filter out wallets that have custom connectors
|
|
30
|
+
const hasCustomConnector = Boolean(getCustomConnectorForKey(key));
|
|
31
|
+
return isSuiWallet && !shouldBeFiltered && !hasCustomConnector;
|
|
21
32
|
})
|
|
22
33
|
.map(([key, wallet]) => {
|
|
23
34
|
// Currently we only support wallet standard wallets
|
|
@@ -40,7 +51,21 @@ const fetchSuiInjectedWalletConnectors = ({ walletBook, }) => {
|
|
|
40
51
|
.filter((wallet) => { var _a; return (_a = wallet.features) === null || _a === void 0 ? void 0 : _a['sui:signPersonalMessage']; })
|
|
41
52
|
.map((wallet) => {
|
|
42
53
|
const sanitizedName = sanitizeName(wallet.name);
|
|
54
|
+
const customConnector = getCustomConnectorForKey(sanitizedName);
|
|
43
55
|
const isInstalled = true;
|
|
56
|
+
if (customConnector) {
|
|
57
|
+
return class extends customConnector {
|
|
58
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
59
|
+
constructor(props) {
|
|
60
|
+
super(wallet.name, isInstalled, Object.assign({ metadata: {
|
|
61
|
+
groupKey: sanitizedName,
|
|
62
|
+
icon: wallet.icon,
|
|
63
|
+
id: wallet.name,
|
|
64
|
+
name: wallet.name,
|
|
65
|
+
}, name: wallet.name, overrideKey: `${sanitizedName}sui`, wallet: wallet }, props));
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
}
|
|
44
69
|
return class extends Injected {
|
|
45
70
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
46
71
|
constructor(props) {
|
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
5
|
+
|
|
6
|
+
var _tslib = require('../../../_virtual/_tslib.cjs');
|
|
7
|
+
var utils = require('@dynamic-labs/utils');
|
|
8
|
+
var networkHelpers = require('../../utils/network/networkHelpers.cjs');
|
|
9
|
+
var injected = require('../injected/injected.cjs');
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Slush Wallet Connector with Multi-Account Support
|
|
13
|
+
*
|
|
14
|
+
* This connector extends the base Injected connector to support multiple
|
|
15
|
+
* wallet accounts per connection prompt. Unlike other Sui wallets that only
|
|
16
|
+
* allow one account at a time, Slush wallet can connect multiple accounts
|
|
17
|
+
* simultaneously.
|
|
18
|
+
*
|
|
19
|
+
* Key features:
|
|
20
|
+
* - Tracks multiple wallet accounts (accounts array)
|
|
21
|
+
* - Filters new accounts to allow only one new address per connection
|
|
22
|
+
* - Supports setting a primary account for operations
|
|
23
|
+
* - Handles account switching for transactions and signing
|
|
24
|
+
*/
|
|
25
|
+
class Slush extends injected.Injected {
|
|
26
|
+
constructor() {
|
|
27
|
+
super(...arguments);
|
|
28
|
+
this.name = 'Slush — A Sui wallet';
|
|
29
|
+
this.overrideKey = 'slushsui';
|
|
30
|
+
/** Tracks all wallet accounts returned by the wallet */
|
|
31
|
+
this.accounts = [];
|
|
32
|
+
}
|
|
33
|
+
/** Tracks the primary/active wallet account (first account by default) */
|
|
34
|
+
getPrimaryAccount() {
|
|
35
|
+
return this.accounts[0];
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Set a specific account as the primary account by address.
|
|
39
|
+
* This moves the specified account to the front of the accounts array.
|
|
40
|
+
* @param address - The address of the account to set as primary
|
|
41
|
+
* @returns true if the account was found and set as primary, false otherwise
|
|
42
|
+
*/
|
|
43
|
+
setPrimaryAccount(account) {
|
|
44
|
+
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
45
|
+
if (!account) {
|
|
46
|
+
this.accounts = [];
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
return this.setPrimaryAccountAddress(account.address);
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
setPrimaryAccountAddress(address) {
|
|
53
|
+
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
54
|
+
var _a;
|
|
55
|
+
const accountIndex = this.accounts.findIndex((acc) => acc.address === address);
|
|
56
|
+
if (accountIndex === -1) {
|
|
57
|
+
this.logger.error(`[setPrimaryAccount] Account with address ${address} not found for ${this.name}`);
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
if (accountIndex === 0) {
|
|
61
|
+
// Already primary
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
// Move the account to the front
|
|
65
|
+
this.logger.debug(`[${this.name}] [setPrimaryAccount] Moving account to primary position`, {
|
|
66
|
+
accountIndex,
|
|
67
|
+
address,
|
|
68
|
+
currentAccountAddresses: this.accounts.map((acc) => acc.address),
|
|
69
|
+
});
|
|
70
|
+
const [targetAccount] = this.accounts.splice(accountIndex, 1);
|
|
71
|
+
this.accounts.unshift(targetAccount);
|
|
72
|
+
this.logger.debug(`[setPrimaryAccount] Set account ${address} as primary account for ${this.name}`);
|
|
73
|
+
// Update the active network ID based on the new primary account
|
|
74
|
+
const primaryChain = (_a = this.getPrimaryAccount()) === null || _a === void 0 ? void 0 : _a.chains[0];
|
|
75
|
+
if (primaryChain) {
|
|
76
|
+
this.activeNetworkId = networkHelpers.getSuiNetworkIdFromName(primaryChain, this.suiNetworks);
|
|
77
|
+
}
|
|
78
|
+
return true;
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Connect to the wallet using the standard:connect feature.
|
|
83
|
+
*
|
|
84
|
+
* Any currently connected wallet will be disconnected first.
|
|
85
|
+
* This happens because we want the user to reselect which wallets they want connected.
|
|
86
|
+
*
|
|
87
|
+
* We only allow adding one new wallet connection per manual user connection.
|
|
88
|
+
*/
|
|
89
|
+
connect() {
|
|
90
|
+
return _tslib.__awaiter(this, arguments, void 0, function* ({ silent = false, } = {}) {
|
|
91
|
+
var _a, _b, _c;
|
|
92
|
+
this.logger.debug(`[${this.name}] [connect] Initiating connection`, {
|
|
93
|
+
isConnecting: this.isConnecting,
|
|
94
|
+
silent,
|
|
95
|
+
});
|
|
96
|
+
if (this.isConnecting) {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
const connectFeature = (_a = this.getFeatures()) === null || _a === void 0 ? void 0 : _a['standard:connect'];
|
|
100
|
+
if (!connectFeature) {
|
|
101
|
+
if (silent) {
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
throw new utils.DynamicError('Wallet does not support standard:connect');
|
|
105
|
+
}
|
|
106
|
+
// Start connecting
|
|
107
|
+
this.isConnecting = true;
|
|
108
|
+
try {
|
|
109
|
+
const disconnectFeature = (_b = this.getFeatures()) === null || _b === void 0 ? void 0 : _b['standard:disconnect'];
|
|
110
|
+
if (disconnectFeature) {
|
|
111
|
+
yield disconnectFeature.disconnect();
|
|
112
|
+
}
|
|
113
|
+
const response = yield connectFeature.connect(silent ? { silent } : undefined);
|
|
114
|
+
this.logger.debug(`[${this.name}] [connect] Connection returned accounts: ${response === null || response === void 0 ? void 0 : response.accounts.length}`);
|
|
115
|
+
this.logger.debug(`[${this.name}] [connect] Received accounts from wallet`, {
|
|
116
|
+
accountAddresses: response === null || response === void 0 ? void 0 : response.accounts.map((acc) => acc.address),
|
|
117
|
+
accountCount: response === null || response === void 0 ? void 0 : response.accounts.length,
|
|
118
|
+
});
|
|
119
|
+
// Store all accounts returned by the wallet (create a mutable copy)
|
|
120
|
+
const newAccounts = (response === null || response === void 0 ? void 0 : response.accounts) ? [...response.accounts] : [];
|
|
121
|
+
if (this.hasAccountsChanged(newAccounts)) {
|
|
122
|
+
const filteredAccounts = this.filterAccountsForSingleWalletConstraint({
|
|
123
|
+
newAccounts,
|
|
124
|
+
});
|
|
125
|
+
this.logger.logVerboseTroubleshootingMessage(`[${this.name}] [connect] Accounts changed, applying filter`, {
|
|
126
|
+
currentAccounts: this.accounts.map((acc) => acc.address),
|
|
127
|
+
newAccounts: filteredAccounts.map((acc) => acc.address),
|
|
128
|
+
});
|
|
129
|
+
this.accounts = filteredAccounts;
|
|
130
|
+
}
|
|
131
|
+
const primaryChain = (_c = this.getPrimaryAccount()) === null || _c === void 0 ? void 0 : _c.chains[0];
|
|
132
|
+
if (primaryChain) {
|
|
133
|
+
this.activeNetworkId = networkHelpers.getSuiNetworkIdFromName(primaryChain, this.suiNetworks);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
catch (error) {
|
|
137
|
+
this.logger.error(error);
|
|
138
|
+
if (silent) {
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
throw new utils.DynamicError('Connection failed');
|
|
142
|
+
}
|
|
143
|
+
finally {
|
|
144
|
+
this.isConnecting = false;
|
|
145
|
+
}
|
|
146
|
+
this.setupEventListeners();
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
validateActiveWallet(expectedAddress) {
|
|
150
|
+
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
151
|
+
const addresses = yield this.getConnectedAccounts();
|
|
152
|
+
const isWalletActive = addresses.find((address) => address === expectedAddress);
|
|
153
|
+
if (isWalletActive) {
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
return this.handleWalletNotActive({
|
|
157
|
+
activeAddress: (yield this.getConnectedAccounts())[0],
|
|
158
|
+
expectedAddress,
|
|
159
|
+
});
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
/** Get the wallet address by connecting to the current account */
|
|
163
|
+
getAddress() {
|
|
164
|
+
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
165
|
+
this.logger.debug(`[${this.name}] [getAddress] called, attempting to obtain the account address`);
|
|
166
|
+
if (this.handleInAppBrowserGetAddress()) {
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
const previousAddresses = this.accounts.map((account) => account.address);
|
|
170
|
+
yield this.connect();
|
|
171
|
+
const newAddresses = this.accounts.map((account) => account.address);
|
|
172
|
+
// If there is a new account, return the new address
|
|
173
|
+
const newAddress = newAddresses.find((address) => !previousAddresses.includes(address));
|
|
174
|
+
if (newAddress) {
|
|
175
|
+
yield this.setPrimaryAccountAddress(newAddress);
|
|
176
|
+
this.logger.debug(`[${this.name}] [getAddress] New account added`, {
|
|
177
|
+
accountAddresses: this.accounts.map((acc) => acc.address),
|
|
178
|
+
newAddress,
|
|
179
|
+
});
|
|
180
|
+
return newAddress;
|
|
181
|
+
}
|
|
182
|
+
this.logger.logVerboseTroubleshootingMessage(`[${this.name}] [setupEventListeners] No new address to add`, {
|
|
183
|
+
accountAddresses: this.accounts.map((acc) => acc.address),
|
|
184
|
+
newAddresses,
|
|
185
|
+
});
|
|
186
|
+
if (newAddresses.length === 0) {
|
|
187
|
+
throw new utils.DynamicError('No account found');
|
|
188
|
+
}
|
|
189
|
+
return newAddresses[0];
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
getConnectedAccounts() {
|
|
193
|
+
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
194
|
+
if (this.accounts.length === 0) {
|
|
195
|
+
yield this.connect({ silent: true });
|
|
196
|
+
}
|
|
197
|
+
// Return all connected account addresses
|
|
198
|
+
return this.accounts.map((account) => account.address);
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Helper to check if accounts have changed by comparing addresses.
|
|
203
|
+
* Accounts are compared in a sorted order to handle cases where the order changes.
|
|
204
|
+
*
|
|
205
|
+
* @param newAccounts - The new accounts to compare against current accounts
|
|
206
|
+
* @returns true if accounts have changed, false otherwise
|
|
207
|
+
*/
|
|
208
|
+
hasAccountsChanged(newAccounts) {
|
|
209
|
+
const currentAddresses = this.accounts
|
|
210
|
+
.map((acc) => acc.address)
|
|
211
|
+
.sort()
|
|
212
|
+
.join(',');
|
|
213
|
+
const newAddresses = newAccounts
|
|
214
|
+
.map((acc) => acc.address)
|
|
215
|
+
.sort()
|
|
216
|
+
.join(',');
|
|
217
|
+
return currentAddresses !== newAddresses;
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Filters new accounts to enforce the SDK's single-wallet connection constraint.
|
|
221
|
+
* The Dynamic SDK only supports connecting one wallet at a time.
|
|
222
|
+
* This method ensures that at most one NEW address is added to the existing accounts.
|
|
223
|
+
*
|
|
224
|
+
* @param newAccounts - The new accounts returned by the wallet
|
|
225
|
+
* @returns Filtered accounts with at most one new address added
|
|
226
|
+
*/
|
|
227
|
+
filterAccountsForSingleWalletConstraint({ newAccounts, }) {
|
|
228
|
+
if (this.accounts.length === 0) {
|
|
229
|
+
return [newAccounts[0]];
|
|
230
|
+
}
|
|
231
|
+
// Keep all currently connected accounts that are still in the new accounts list
|
|
232
|
+
const currentAddresses = new Set(this.accounts.map((acc) => acc.address.toLowerCase()));
|
|
233
|
+
const filteredAccounts = newAccounts.filter((acc) => currentAddresses.has(acc.address.toLowerCase()));
|
|
234
|
+
// Find new accounts that aren't in the current list
|
|
235
|
+
const trulyNewAccounts = newAccounts.filter((acc) => !currentAddresses.has(acc.address.toLowerCase()));
|
|
236
|
+
// Allow at most one new account to be added
|
|
237
|
+
if (trulyNewAccounts.length > 0) {
|
|
238
|
+
filteredAccounts.push(trulyNewAccounts[0]);
|
|
239
|
+
}
|
|
240
|
+
return filteredAccounts;
|
|
241
|
+
}
|
|
242
|
+
handleAccountChange() {
|
|
243
|
+
// We intentionally ignore account change events from Slush wallets.
|
|
244
|
+
// Slush wallets support connecting multiple accounts simultaneously,
|
|
245
|
+
// but the Dynamic SDK only supports connecting one wallet at a time.
|
|
246
|
+
// To enforce this constraint, we only allow adding new accounts through the connect()
|
|
247
|
+
// method, where we can properly filter and ensure at most one new account is added.
|
|
248
|
+
// Account change events are therefore ignored to prevent bypassing this limitation.
|
|
249
|
+
}
|
|
250
|
+
signMessage(messageToSign_1) {
|
|
251
|
+
const _super = Object.create(null, {
|
|
252
|
+
signMessage: { get: () => super.signMessage }
|
|
253
|
+
});
|
|
254
|
+
return _tslib.__awaiter(this, arguments, void 0, function* (messageToSign, { address } = {}) {
|
|
255
|
+
if (address) {
|
|
256
|
+
yield this.setPrimaryAccountAddress(address);
|
|
257
|
+
}
|
|
258
|
+
return _super.signMessage.call(this, messageToSign);
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
/** Function used to create transactions in the SDK interface */
|
|
262
|
+
createUiTransaction(from) {
|
|
263
|
+
const _super = Object.create(null, {
|
|
264
|
+
createUiTransaction: { get: () => super.createUiTransaction }
|
|
265
|
+
});
|
|
266
|
+
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
267
|
+
if (this.accounts.length === 0) {
|
|
268
|
+
throw new utils.DynamicError('No account connected');
|
|
269
|
+
}
|
|
270
|
+
yield this.setPrimaryAccountAddress(from);
|
|
271
|
+
return _super.createUiTransaction.call(this, from);
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
signAndExecuteTransactionFeature(_a) {
|
|
275
|
+
const _super = Object.create(null, {
|
|
276
|
+
signAndExecuteTransactionFeature: { get: () => super.signAndExecuteTransactionFeature }
|
|
277
|
+
});
|
|
278
|
+
return _tslib.__awaiter(this, arguments, void 0, function* ({ transaction, legacyOptions, }) {
|
|
279
|
+
const { sender } = transaction.getData();
|
|
280
|
+
if (sender) {
|
|
281
|
+
yield this.setPrimaryAccountAddress(sender);
|
|
282
|
+
}
|
|
283
|
+
return _super.signAndExecuteTransactionFeature.call(this, {
|
|
284
|
+
legacyOptions,
|
|
285
|
+
transaction,
|
|
286
|
+
});
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
signTransactionFeature(_a) {
|
|
290
|
+
const _super = Object.create(null, {
|
|
291
|
+
signTransactionFeature: { get: () => super.signTransactionFeature }
|
|
292
|
+
});
|
|
293
|
+
return _tslib.__awaiter(this, arguments, void 0, function* ({ transaction, }) {
|
|
294
|
+
const { sender } = transaction.getData();
|
|
295
|
+
if (sender) {
|
|
296
|
+
yield this.setPrimaryAccountAddress(sender);
|
|
297
|
+
}
|
|
298
|
+
return _super.signTransactionFeature.call(this, { transaction });
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
Object.defineProperty(Slush, 'key', {
|
|
303
|
+
value: 'slushsui',
|
|
304
|
+
writable: false,
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
exports.Slush = Slush;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { SuiSignAndExecuteTransactionBlockOutput, SuiSignAndExecuteTransactionOutput, WalletAccount, SignedTransaction, SuiSignTransactionBlockOutput } from '@mysten/wallet-standard';
|
|
2
|
+
import { Transaction } from '@mysten/sui/transactions';
|
|
3
|
+
import { ExecuteTransactionRequestType, SuiTransactionBlockResponseOptions } from '@mysten/sui/client';
|
|
4
|
+
import { Injected } from '../injected/injected';
|
|
5
|
+
/**
|
|
6
|
+
* Slush Wallet Connector with Multi-Account Support
|
|
7
|
+
*
|
|
8
|
+
* This connector extends the base Injected connector to support multiple
|
|
9
|
+
* wallet accounts per connection prompt. Unlike other Sui wallets that only
|
|
10
|
+
* allow one account at a time, Slush wallet can connect multiple accounts
|
|
11
|
+
* simultaneously.
|
|
12
|
+
*
|
|
13
|
+
* Key features:
|
|
14
|
+
* - Tracks multiple wallet accounts (accounts array)
|
|
15
|
+
* - Filters new accounts to allow only one new address per connection
|
|
16
|
+
* - Supports setting a primary account for operations
|
|
17
|
+
* - Handles account switching for transactions and signing
|
|
18
|
+
*/
|
|
19
|
+
export declare class Slush extends Injected {
|
|
20
|
+
name: string;
|
|
21
|
+
overrideKey: string;
|
|
22
|
+
/** Tracks all wallet accounts returned by the wallet */
|
|
23
|
+
protected accounts: WalletAccount[];
|
|
24
|
+
/** Tracks the primary/active wallet account (first account by default) */
|
|
25
|
+
getPrimaryAccount(): WalletAccount | undefined;
|
|
26
|
+
/**
|
|
27
|
+
* Set a specific account as the primary account by address.
|
|
28
|
+
* This moves the specified account to the front of the accounts array.
|
|
29
|
+
* @param address - The address of the account to set as primary
|
|
30
|
+
* @returns true if the account was found and set as primary, false otherwise
|
|
31
|
+
*/
|
|
32
|
+
setPrimaryAccount(account: WalletAccount | undefined): Promise<boolean | undefined>;
|
|
33
|
+
private setPrimaryAccountAddress;
|
|
34
|
+
/**
|
|
35
|
+
* Connect to the wallet using the standard:connect feature.
|
|
36
|
+
*
|
|
37
|
+
* Any currently connected wallet will be disconnected first.
|
|
38
|
+
* This happens because we want the user to reselect which wallets they want connected.
|
|
39
|
+
*
|
|
40
|
+
* We only allow adding one new wallet connection per manual user connection.
|
|
41
|
+
*/
|
|
42
|
+
connect({ silent, }?: {
|
|
43
|
+
silent?: boolean;
|
|
44
|
+
}): Promise<void>;
|
|
45
|
+
validateActiveWallet(expectedAddress: string): Promise<void>;
|
|
46
|
+
/** Get the wallet address by connecting to the current account */
|
|
47
|
+
getAddress(): Promise<string | undefined>;
|
|
48
|
+
getConnectedAccounts(): Promise<string[]>;
|
|
49
|
+
/**
|
|
50
|
+
* Helper to check if accounts have changed by comparing addresses.
|
|
51
|
+
* Accounts are compared in a sorted order to handle cases where the order changes.
|
|
52
|
+
*
|
|
53
|
+
* @param newAccounts - The new accounts to compare against current accounts
|
|
54
|
+
* @returns true if accounts have changed, false otherwise
|
|
55
|
+
*/
|
|
56
|
+
private hasAccountsChanged;
|
|
57
|
+
/**
|
|
58
|
+
* Filters new accounts to enforce the SDK's single-wallet connection constraint.
|
|
59
|
+
* The Dynamic SDK only supports connecting one wallet at a time.
|
|
60
|
+
* This method ensures that at most one NEW address is added to the existing accounts.
|
|
61
|
+
*
|
|
62
|
+
* @param newAccounts - The new accounts returned by the wallet
|
|
63
|
+
* @returns Filtered accounts with at most one new address added
|
|
64
|
+
*/
|
|
65
|
+
private filterAccountsForSingleWalletConstraint;
|
|
66
|
+
handleAccountChange(): void;
|
|
67
|
+
signMessage(messageToSign: string, { address }?: {
|
|
68
|
+
address?: string;
|
|
69
|
+
}): Promise<string | undefined>;
|
|
70
|
+
/** Function used to create transactions in the SDK interface */
|
|
71
|
+
createUiTransaction(from: string): Promise<import("dist/packages/types/src").IUITransaction>;
|
|
72
|
+
signAndExecuteTransactionFeature({ transaction, legacyOptions, }: {
|
|
73
|
+
transaction: Transaction;
|
|
74
|
+
legacyOptions?: {
|
|
75
|
+
options?: SuiTransactionBlockResponseOptions;
|
|
76
|
+
requestType?: ExecuteTransactionRequestType;
|
|
77
|
+
};
|
|
78
|
+
}): Promise<SuiSignAndExecuteTransactionOutput | SuiSignAndExecuteTransactionBlockOutput>;
|
|
79
|
+
signTransactionFeature({ transaction, }: {
|
|
80
|
+
transaction: Transaction;
|
|
81
|
+
}): Promise<SignedTransaction | SuiSignTransactionBlockOutput>;
|
|
82
|
+
}
|