@rango-dev/wallets-core 0.49.1-next.0 → 0.49.1-next.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/dist/namespaces/common/hooks/changeAccountSubscriber.d.ts +65 -0
- package/dist/namespaces/common/hooks/changeAccountSubscriber.d.ts.map +1 -0
- package/dist/namespaces/common/hooks/changeAccountSubscriber.test.d.ts +2 -0
- package/dist/namespaces/common/hooks/changeAccountSubscriber.test.d.ts.map +1 -0
- package/dist/namespaces/evm/actions.d.ts +2 -4
- package/dist/namespaces/evm/actions.d.ts.map +1 -1
- package/dist/namespaces/evm/builders.d.ts +3 -1
- package/dist/namespaces/evm/builders.d.ts.map +1 -1
- package/dist/namespaces/evm/hooks.d.ts +5 -0
- package/dist/namespaces/evm/hooks.d.ts.map +1 -0
- package/dist/namespaces/evm/mod.d.ts +1 -0
- package/dist/namespaces/evm/mod.d.ts.map +1 -1
- package/dist/namespaces/evm/mod.js +1 -1
- package/dist/namespaces/evm/mod.js.map +4 -4
- package/dist/namespaces/evm/utils.d.ts +1 -0
- package/dist/namespaces/evm/utils.d.ts.map +1 -1
- package/dist/namespaces/solana/actions.d.ts +1 -3
- package/dist/namespaces/solana/actions.d.ts.map +1 -1
- package/dist/namespaces/solana/builders.d.ts +3 -1
- package/dist/namespaces/solana/builders.d.ts.map +1 -1
- package/dist/namespaces/solana/hooks.d.ts +4 -0
- package/dist/namespaces/solana/hooks.d.ts.map +1 -0
- package/dist/namespaces/solana/mod.d.ts +1 -0
- package/dist/namespaces/solana/mod.d.ts.map +1 -1
- package/dist/namespaces/solana/mod.js +1 -1
- package/dist/namespaces/solana/mod.js.map +4 -4
- package/dist/namespaces/solana/utils.d.ts +1 -0
- package/dist/namespaces/solana/utils.d.ts.map +1 -1
- package/dist/namespaces/sui/actions.d.ts +1 -6
- package/dist/namespaces/sui/actions.d.ts.map +1 -1
- package/dist/namespaces/sui/builders.d.ts +6 -1
- package/dist/namespaces/sui/builders.d.ts.map +1 -1
- package/dist/namespaces/sui/hooks.d.ts +4 -0
- package/dist/namespaces/sui/hooks.d.ts.map +1 -0
- package/dist/namespaces/sui/mod.d.ts +1 -0
- package/dist/namespaces/sui/mod.d.ts.map +1 -1
- package/dist/namespaces/sui/mod.js +1 -1
- package/dist/namespaces/sui/mod.js.map +4 -4
- package/dist/namespaces/sui/types.d.ts +5 -1
- package/dist/namespaces/sui/types.d.ts.map +1 -1
- package/dist/namespaces/sui/utils.d.ts +3 -0
- package/dist/namespaces/sui/utils.d.ts.map +1 -1
- package/dist/wallets-core.build.json +1 -1
- package/package.json +1 -1
- package/src/namespaces/common/hooks/changeAccountSubscriber.test.ts +162 -0
- package/src/namespaces/common/hooks/changeAccountSubscriber.ts +188 -0
- package/src/namespaces/evm/actions.ts +8 -127
- package/src/namespaces/evm/builders.ts +39 -1
- package/src/namespaces/evm/hooks.ts +43 -0
- package/src/namespaces/evm/mod.ts +1 -0
- package/src/namespaces/evm/utils.ts +31 -1
- package/src/namespaces/solana/actions.ts +2 -56
- package/src/namespaces/solana/builders.ts +25 -1
- package/src/namespaces/solana/hooks.ts +10 -0
- package/src/namespaces/solana/mod.ts +1 -0
- package/src/namespaces/solana/utils.ts +18 -0
- package/src/namespaces/sui/actions.ts +1 -61
- package/src/namespaces/sui/builders.ts +33 -2
- package/src/namespaces/sui/hooks.ts +10 -0
- package/src/namespaces/sui/mod.ts +1 -0
- package/src/namespaces/sui/types.ts +13 -2
- package/src/namespaces/sui/utils.ts +14 -0
|
@@ -1,26 +1,18 @@
|
|
|
1
|
-
import type { EIP1193EventMap } from './eip1193.js';
|
|
2
1
|
import type { ConnectOptions, EvmActions, ProviderAPI } from './types.js';
|
|
3
|
-
import type { Context
|
|
4
|
-
import type {
|
|
5
|
-
CanEagerConnect,
|
|
6
|
-
SubscriberCleanUp,
|
|
7
|
-
} from '../../hub/namespaces/types.js';
|
|
8
|
-
import type { CaipAccount } from '../../types/accounts.js';
|
|
2
|
+
import type { Context } from '../../hub/namespaces/mod.js';
|
|
3
|
+
import type { CanEagerConnect } from '../../hub/namespaces/types.js';
|
|
9
4
|
import type { FunctionWithContext } from '../../types/actions.js';
|
|
10
5
|
|
|
11
|
-
import { AccountId } from 'caip';
|
|
12
|
-
|
|
13
6
|
import { recommended as commonRecommended } from '../common/actions.js';
|
|
14
7
|
|
|
15
|
-
import { CAIP_NAMESPACE } from './constants.js';
|
|
16
8
|
import {
|
|
17
9
|
filterAndGetEvmBlockchainNames,
|
|
10
|
+
formatAccountsToCAIP,
|
|
18
11
|
getAccounts,
|
|
19
12
|
switchOrAddNetwork,
|
|
20
13
|
} from './utils.js';
|
|
21
14
|
|
|
22
15
|
export const recommended = [...commonRecommended];
|
|
23
|
-
const CHAIN_ID_RADIX = 16;
|
|
24
16
|
export function connect(
|
|
25
17
|
instance: () => ProviderAPI,
|
|
26
18
|
options?: ConnectOptions
|
|
@@ -50,129 +42,18 @@ export function connect(
|
|
|
50
42
|
|
|
51
43
|
const result = await getAccounts(evmInstance);
|
|
52
44
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
* number (e.g., 1) rather than the standard hexadecimal string (e.g., "0x1").
|
|
57
|
-
* This code block standardizes the `chainId` to the required hex format to
|
|
58
|
-
* prevent downstream errors.
|
|
59
|
-
*/
|
|
60
|
-
let chainId = result.chainId;
|
|
61
|
-
if (typeof chainId === 'number') {
|
|
62
|
-
chainId = `0x${Number(chainId).toString(CHAIN_ID_RADIX)}`;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
const formatAccounts = result.accounts.map(
|
|
66
|
-
(account) =>
|
|
67
|
-
AccountId.format({
|
|
68
|
-
address: account,
|
|
69
|
-
chainId: {
|
|
70
|
-
namespace: CAIP_NAMESPACE,
|
|
71
|
-
reference: chainId,
|
|
72
|
-
},
|
|
73
|
-
}) as CaipAccount
|
|
45
|
+
const formattedAccounts = formatAccountsToCAIP(
|
|
46
|
+
result.accounts,
|
|
47
|
+
result.chainId
|
|
74
48
|
);
|
|
75
49
|
|
|
76
50
|
return {
|
|
77
|
-
accounts:
|
|
78
|
-
network: chainId,
|
|
51
|
+
accounts: formattedAccounts,
|
|
52
|
+
network: result.chainId,
|
|
79
53
|
};
|
|
80
54
|
};
|
|
81
55
|
}
|
|
82
56
|
|
|
83
|
-
export function changeAccountSubscriber(
|
|
84
|
-
instance: () => ProviderAPI
|
|
85
|
-
): [Subscriber<EvmActions>, SubscriberCleanUp<EvmActions>] {
|
|
86
|
-
let eventCallback: EIP1193EventMap['accountsChanged'];
|
|
87
|
-
|
|
88
|
-
// subscriber can be passed to `or`, it will get the error and should rethrow error to pass the error to next `or` or throw error.
|
|
89
|
-
return [
|
|
90
|
-
(context, err) => {
|
|
91
|
-
const evmInstance = instance();
|
|
92
|
-
|
|
93
|
-
if (!evmInstance) {
|
|
94
|
-
throw new Error(
|
|
95
|
-
'Trying to subscribe to your EVM wallet, but seems its instance is not available.'
|
|
96
|
-
);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
const [, setState] = context.state();
|
|
100
|
-
|
|
101
|
-
eventCallback = async (accounts) => {
|
|
102
|
-
/*
|
|
103
|
-
* In Phantom, when user is switching to an account which is not connected to dApp yet, it returns a null.
|
|
104
|
-
* So null means we don't have access to account and we need to disconnect and let the user connect the account.
|
|
105
|
-
*
|
|
106
|
-
* This assumption may not work for other wallets, if that the case, we need to consider a new approach.
|
|
107
|
-
*/
|
|
108
|
-
if (!accounts || accounts.length === 0) {
|
|
109
|
-
context.action('disconnect');
|
|
110
|
-
return;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
const chainId = await evmInstance.request({ method: 'eth_chainId' });
|
|
114
|
-
const formatAccounts = accounts.map((account) =>
|
|
115
|
-
AccountId.format({
|
|
116
|
-
address: account,
|
|
117
|
-
chainId: {
|
|
118
|
-
namespace: CAIP_NAMESPACE,
|
|
119
|
-
reference: chainId,
|
|
120
|
-
},
|
|
121
|
-
})
|
|
122
|
-
);
|
|
123
|
-
|
|
124
|
-
setState('accounts', formatAccounts);
|
|
125
|
-
};
|
|
126
|
-
evmInstance.on('accountsChanged', eventCallback);
|
|
127
|
-
|
|
128
|
-
if (err instanceof Error) {
|
|
129
|
-
throw err;
|
|
130
|
-
}
|
|
131
|
-
},
|
|
132
|
-
(_, err) => {
|
|
133
|
-
const evmInstance = instance();
|
|
134
|
-
|
|
135
|
-
if (eventCallback && evmInstance) {
|
|
136
|
-
evmInstance.removeListener?.('accountsChanged', eventCallback);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
return err;
|
|
140
|
-
},
|
|
141
|
-
];
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
export function changeChainSubscriber(
|
|
145
|
-
instance: () => ProviderAPI
|
|
146
|
-
): [Subscriber<EvmActions>, SubscriberCleanUp<EvmActions>] {
|
|
147
|
-
let eventCallback: EIP1193EventMap['chainChanged'];
|
|
148
|
-
|
|
149
|
-
return [
|
|
150
|
-
(context) => {
|
|
151
|
-
const evmInstance = instance();
|
|
152
|
-
|
|
153
|
-
if (!evmInstance) {
|
|
154
|
-
throw new Error(
|
|
155
|
-
'Trying to subscribe to your EVM wallet, but seems its instance is not available.'
|
|
156
|
-
);
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
const [, setState] = context.state();
|
|
160
|
-
|
|
161
|
-
eventCallback = async (chainId: string) => {
|
|
162
|
-
setState('network', chainId);
|
|
163
|
-
};
|
|
164
|
-
evmInstance.on('chainChanged', eventCallback);
|
|
165
|
-
},
|
|
166
|
-
() => {
|
|
167
|
-
const evmInstance = instance();
|
|
168
|
-
|
|
169
|
-
if (eventCallback && evmInstance) {
|
|
170
|
-
evmInstance.removeListener('chainChanged', eventCallback);
|
|
171
|
-
}
|
|
172
|
-
},
|
|
173
|
-
];
|
|
174
|
-
}
|
|
175
|
-
|
|
176
57
|
export function canEagerConnect(
|
|
177
58
|
instance: () => ProviderAPI | undefined
|
|
178
59
|
): CanEagerConnect<EvmActions> {
|
|
@@ -1,12 +1,18 @@
|
|
|
1
|
-
import type { EvmActions } from './types.js';
|
|
1
|
+
import type { EvmActions, ProviderAPI } from './types.js';
|
|
2
|
+
|
|
3
|
+
import { AccountId } from 'caip';
|
|
2
4
|
|
|
3
5
|
import { ActionBuilder } from '../../mod.js';
|
|
6
|
+
import { ChangeAccountSubscriberBuilder } from '../common/hooks/changeAccountSubscriber.js';
|
|
4
7
|
import {
|
|
5
8
|
connectAndUpdateStateForMultiNetworks,
|
|
6
9
|
intoConnecting,
|
|
7
10
|
intoConnectionFinished,
|
|
8
11
|
} from '../common/mod.js';
|
|
9
12
|
|
|
13
|
+
import { CAIP_NAMESPACE } from './constants.js';
|
|
14
|
+
|
|
15
|
+
// Actions
|
|
10
16
|
export const connect = () =>
|
|
11
17
|
new ActionBuilder<EvmActions, 'connect'>('connect')
|
|
12
18
|
.and(connectAndUpdateStateForMultiNetworks)
|
|
@@ -17,3 +23,35 @@ export const canEagerConnect = () =>
|
|
|
17
23
|
new ActionBuilder<EvmActions, 'canEagerConnect'>('canEagerConnect');
|
|
18
24
|
export const canSwitchNetwork = () =>
|
|
19
25
|
new ActionBuilder<EvmActions, 'canSwitchNetwork'>('canSwitchNetwork');
|
|
26
|
+
|
|
27
|
+
// Hooks
|
|
28
|
+
export const changeAccountSubscriber = (getInstance: () => ProviderAPI) =>
|
|
29
|
+
new ChangeAccountSubscriberBuilder<string[], ProviderAPI>()
|
|
30
|
+
.getInstance(getInstance)
|
|
31
|
+
.validateEventPayload(
|
|
32
|
+
(accounts) =>
|
|
33
|
+
/*
|
|
34
|
+
* In some wallets, when a user switches to an account not yet connected to the dApp, it returns null.
|
|
35
|
+
* A null value indicates no access to the account, requiring a disconnect and user reconnection.
|
|
36
|
+
* This behavior may vary across different wallets, and if so, a different approach may be needed.
|
|
37
|
+
*/
|
|
38
|
+
accounts && accounts.length !== 0
|
|
39
|
+
)
|
|
40
|
+
.format(async (instance, accounts) => {
|
|
41
|
+
const chainId = await instance.request({ method: 'eth_chainId' });
|
|
42
|
+
return accounts.map((account) =>
|
|
43
|
+
AccountId.format({
|
|
44
|
+
address: account,
|
|
45
|
+
chainId: {
|
|
46
|
+
namespace: CAIP_NAMESPACE,
|
|
47
|
+
reference: chainId,
|
|
48
|
+
},
|
|
49
|
+
})
|
|
50
|
+
);
|
|
51
|
+
})
|
|
52
|
+
.addEventListener((instance, callback) => {
|
|
53
|
+
instance.on('accountsChanged', callback);
|
|
54
|
+
})
|
|
55
|
+
.removeEventListener((instance, callback) => {
|
|
56
|
+
instance.removeListener?.('accountsChanged', callback);
|
|
57
|
+
});
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { EIP1193EventMap } from './eip1193.js';
|
|
2
|
+
import type { EvmActions, ProviderAPI } from './types.js';
|
|
3
|
+
import type { Subscriber, SubscriberCleanUp } from '../../mod.js';
|
|
4
|
+
|
|
5
|
+
import { builders } from './mod.js';
|
|
6
|
+
|
|
7
|
+
export function changeAccountSubscriber(
|
|
8
|
+
instance: () => ProviderAPI
|
|
9
|
+
): [Subscriber<EvmActions>, SubscriberCleanUp<EvmActions>] {
|
|
10
|
+
return builders.changeAccountSubscriber(instance).build();
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function changeChainSubscriber(
|
|
14
|
+
instance: () => ProviderAPI
|
|
15
|
+
): [Subscriber<EvmActions>, SubscriberCleanUp<EvmActions>] {
|
|
16
|
+
let eventCallback: EIP1193EventMap['chainChanged'];
|
|
17
|
+
|
|
18
|
+
return [
|
|
19
|
+
(context) => {
|
|
20
|
+
const evmInstance = instance();
|
|
21
|
+
|
|
22
|
+
if (!evmInstance) {
|
|
23
|
+
throw new Error(
|
|
24
|
+
'Trying to subscribe to your EVM wallet, but seems its instance is not available.'
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const [, setState] = context.state();
|
|
29
|
+
|
|
30
|
+
eventCallback = async (chainId: string) => {
|
|
31
|
+
setState('network', chainId);
|
|
32
|
+
};
|
|
33
|
+
evmInstance.on('chainChanged', eventCallback);
|
|
34
|
+
},
|
|
35
|
+
() => {
|
|
36
|
+
const evmInstance = instance();
|
|
37
|
+
|
|
38
|
+
if (eventCallback && evmInstance) {
|
|
39
|
+
evmInstance.removeListener('chainChanged', eventCallback);
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
];
|
|
43
|
+
}
|
|
@@ -1,16 +1,33 @@
|
|
|
1
1
|
import type { Chain, ChainId, ProviderAPI } from './types.js';
|
|
2
|
+
import type { CaipAccount } from '../../types/accounts.js';
|
|
2
3
|
|
|
4
|
+
import { AccountId } from 'caip';
|
|
3
5
|
import { type BlockchainMeta, evmBlockchains } from 'rango-types';
|
|
4
6
|
|
|
7
|
+
import { CAIP_NAMESPACE } from './constants.js';
|
|
8
|
+
|
|
9
|
+
const CHAIN_ID_RADIX = 16;
|
|
10
|
+
|
|
5
11
|
export async function getAccounts(provider: ProviderAPI) {
|
|
6
12
|
const [accounts, chainId] = await Promise.all([
|
|
7
13
|
provider.request({ method: 'eth_requestAccounts' }),
|
|
8
14
|
provider.request({ method: 'eth_chainId' }),
|
|
9
15
|
]);
|
|
16
|
+
/*
|
|
17
|
+
* Trust Wallet Compatibility Fix:
|
|
18
|
+
* Trust Wallet's in-app browser has been observed to return the `chainId` as a
|
|
19
|
+
* number (e.g., 1) rather than the standard hexadecimal string (e.g., "0x1").
|
|
20
|
+
* This code block standardizes the `chainId` to the required hex format to
|
|
21
|
+
* prevent downstream errors.
|
|
22
|
+
*/
|
|
23
|
+
let standardChainId = chainId;
|
|
24
|
+
if (typeof standardChainId === 'number') {
|
|
25
|
+
standardChainId = `0x${Number(chainId).toString(CHAIN_ID_RADIX)}`;
|
|
26
|
+
}
|
|
10
27
|
|
|
11
28
|
return {
|
|
12
29
|
accounts,
|
|
13
|
-
chainId,
|
|
30
|
+
chainId: standardChainId,
|
|
14
31
|
};
|
|
15
32
|
}
|
|
16
33
|
|
|
@@ -74,3 +91,16 @@ export function isUserRejectionError(error: unknown): boolean {
|
|
|
74
91
|
}
|
|
75
92
|
return false;
|
|
76
93
|
}
|
|
94
|
+
|
|
95
|
+
export function formatAccountsToCAIP(accounts: string[], chainId: string) {
|
|
96
|
+
return accounts.map(
|
|
97
|
+
(account) =>
|
|
98
|
+
AccountId.format({
|
|
99
|
+
address: account,
|
|
100
|
+
chainId: {
|
|
101
|
+
namespace: CAIP_NAMESPACE,
|
|
102
|
+
reference: chainId,
|
|
103
|
+
},
|
|
104
|
+
}) as CaipAccount
|
|
105
|
+
);
|
|
106
|
+
}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import type { ProviderAPI, SolanaActions } from './types.js';
|
|
2
|
-
import type { Context
|
|
3
|
-
import type { SubscriberCleanUp } from '../../hub/namespaces/types.js';
|
|
2
|
+
import type { Context } from '../../hub/namespaces/mod.js';
|
|
4
3
|
import type { CaipAccount } from '../../types/accounts.js';
|
|
5
|
-
import type {
|
|
4
|
+
import type { FunctionWithContext } from '../../types/actions.js';
|
|
6
5
|
|
|
7
6
|
import { AccountId } from 'caip';
|
|
8
7
|
|
|
@@ -13,59 +12,6 @@ import { getAccounts } from './utils.js';
|
|
|
13
12
|
|
|
14
13
|
export const recommended = [...commonRecommended];
|
|
15
14
|
|
|
16
|
-
export function changeAccountSubscriber(
|
|
17
|
-
instance: () => ProviderAPI | undefined
|
|
18
|
-
): [Subscriber<SolanaActions>, SubscriberCleanUp<SolanaActions>] {
|
|
19
|
-
let eventCallback: AnyFunction;
|
|
20
|
-
|
|
21
|
-
// subscriber can be passed to `or`, it will get the error and should rethrow error to pass the error to next `or` or throw error.
|
|
22
|
-
return [
|
|
23
|
-
(context, err) => {
|
|
24
|
-
const solanaInstance = instance();
|
|
25
|
-
|
|
26
|
-
if (!solanaInstance) {
|
|
27
|
-
throw new Error(
|
|
28
|
-
'Trying to subscribe to your Solana wallet, but seems its instance is not available.'
|
|
29
|
-
);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
const [, setState] = context.state();
|
|
33
|
-
|
|
34
|
-
eventCallback = (publicKey) => {
|
|
35
|
-
/*
|
|
36
|
-
* In Phantom, when user is switching to an account which is not connected to dApp yet, it returns a null.
|
|
37
|
-
* So null means we don't have access to account and we 0 need to disconnect and let the user connect the account.
|
|
38
|
-
*/
|
|
39
|
-
if (!publicKey) {
|
|
40
|
-
context.action('disconnect');
|
|
41
|
-
return;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
setState('accounts', [
|
|
45
|
-
AccountId.format({
|
|
46
|
-
address: publicKey.toString(),
|
|
47
|
-
chainId: {
|
|
48
|
-
namespace: CAIP_NAMESPACE,
|
|
49
|
-
reference: CAIP_SOLANA_CHAIN_ID,
|
|
50
|
-
},
|
|
51
|
-
}),
|
|
52
|
-
]);
|
|
53
|
-
};
|
|
54
|
-
solanaInstance.on('accountChanged', eventCallback);
|
|
55
|
-
|
|
56
|
-
return err;
|
|
57
|
-
},
|
|
58
|
-
(_context, err) => {
|
|
59
|
-
const solanaInstance = instance();
|
|
60
|
-
|
|
61
|
-
if (eventCallback && solanaInstance) {
|
|
62
|
-
solanaInstance.off('accountChanged', eventCallback);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
return err;
|
|
66
|
-
},
|
|
67
|
-
];
|
|
68
|
-
}
|
|
69
15
|
export function connect(
|
|
70
16
|
instance: () => ProviderAPI
|
|
71
17
|
): FunctionWithContext<SolanaActions['connect'], Context> {
|
|
@@ -1,14 +1,38 @@
|
|
|
1
|
-
import type { SolanaActions } from './types.js';
|
|
1
|
+
import type { ProviderAPI, SolanaActions } from './types.js';
|
|
2
2
|
|
|
3
3
|
import { ActionBuilder } from '../../mod.js';
|
|
4
|
+
import { ChangeAccountSubscriberBuilder } from '../common/hooks/changeAccountSubscriber.js';
|
|
4
5
|
import {
|
|
5
6
|
connectAndUpdateStateForSingleNetwork,
|
|
6
7
|
intoConnecting,
|
|
7
8
|
intoConnectionFinished,
|
|
8
9
|
} from '../common/mod.js';
|
|
9
10
|
|
|
11
|
+
import { formatAccountsToCAIP } from './utils.js';
|
|
12
|
+
|
|
13
|
+
// Actions
|
|
10
14
|
export const connect = () =>
|
|
11
15
|
new ActionBuilder<SolanaActions, 'connect'>('connect')
|
|
12
16
|
.and(connectAndUpdateStateForSingleNetwork)
|
|
13
17
|
.before(intoConnecting)
|
|
14
18
|
.after(intoConnectionFinished);
|
|
19
|
+
|
|
20
|
+
// Hooks
|
|
21
|
+
export const changeAccountSubscriber = (getInstance: () => ProviderAPI) =>
|
|
22
|
+
new ChangeAccountSubscriberBuilder<string, ProviderAPI>()
|
|
23
|
+
.getInstance(getInstance)
|
|
24
|
+
.validateEventPayload(
|
|
25
|
+
(accounts) =>
|
|
26
|
+
/*
|
|
27
|
+
* In some wallets, when a user switches to an account not yet connected to the dApp, it returns null.
|
|
28
|
+
* A null value indicates no access to the account, requiring a disconnect and user reconnection.
|
|
29
|
+
*/
|
|
30
|
+
!!accounts
|
|
31
|
+
)
|
|
32
|
+
.format(async (_, accounts) => formatAccountsToCAIP([accounts]))
|
|
33
|
+
.addEventListener((instance, callback) => {
|
|
34
|
+
instance.on('accountChanged', callback);
|
|
35
|
+
})
|
|
36
|
+
.removeEventListener((instance, callback) => {
|
|
37
|
+
instance.off('accountChanged', callback);
|
|
38
|
+
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ProviderAPI, SolanaActions } from './types.js';
|
|
2
|
+
import type { Subscriber, SubscriberCleanUp } from '../../mod.js';
|
|
3
|
+
|
|
4
|
+
import { builders } from './mod.js';
|
|
5
|
+
|
|
6
|
+
export function changeAccountSubscriber(
|
|
7
|
+
instance: () => ProviderAPI
|
|
8
|
+
): [Subscriber<SolanaActions>, SubscriberCleanUp<SolanaActions>] {
|
|
9
|
+
return builders.changeAccountSubscriber(instance).build();
|
|
10
|
+
}
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import type { ProviderAPI } from './types.js';
|
|
2
|
+
import type { CaipAccount } from '../../types/accounts.js';
|
|
3
|
+
|
|
4
|
+
import { AccountId } from 'caip';
|
|
2
5
|
|
|
3
6
|
import { LegacyNetworks } from '../../legacy/mod.js';
|
|
4
7
|
|
|
8
|
+
import { CAIP_NAMESPACE, CAIP_SOLANA_CHAIN_ID } from './constants.js';
|
|
9
|
+
|
|
5
10
|
export async function getAccounts(provider: ProviderAPI) {
|
|
6
11
|
const solanaResponse = await provider.connect();
|
|
7
12
|
const account = solanaResponse.publicKey.toString();
|
|
@@ -10,3 +15,16 @@ export async function getAccounts(provider: ProviderAPI) {
|
|
|
10
15
|
chainId: LegacyNetworks.SOLANA,
|
|
11
16
|
};
|
|
12
17
|
}
|
|
18
|
+
|
|
19
|
+
export function formatAccountsToCAIP(accounts: string[]) {
|
|
20
|
+
return accounts.map(
|
|
21
|
+
(account) =>
|
|
22
|
+
AccountId.format({
|
|
23
|
+
address: account.toString(),
|
|
24
|
+
chainId: {
|
|
25
|
+
namespace: CAIP_NAMESPACE,
|
|
26
|
+
reference: CAIP_SOLANA_CHAIN_ID,
|
|
27
|
+
},
|
|
28
|
+
}) as CaipAccount
|
|
29
|
+
);
|
|
30
|
+
}
|
|
@@ -1,68 +1,8 @@
|
|
|
1
1
|
import type { SuiActions } from './types.js';
|
|
2
|
-
import type {
|
|
3
|
-
import type {
|
|
4
|
-
CanEagerConnect,
|
|
5
|
-
SubscriberCleanUp,
|
|
6
|
-
} from '../../hub/namespaces/types.js';
|
|
7
|
-
import type { StandardEventsChangeProperties } from '@mysten/wallet-standard';
|
|
2
|
+
import type { CanEagerConnect } from '../../hub/namespaces/types.js';
|
|
8
3
|
|
|
9
|
-
import { AccountId } from 'caip';
|
|
10
|
-
|
|
11
|
-
import { CAIP_NAMESPACE, CAIP_SUI_CHAIN_ID } from './constants.js';
|
|
12
4
|
import { getInstanceOrThrow } from './mod.js';
|
|
13
5
|
|
|
14
|
-
interface ChangeAccountSubscriberParams {
|
|
15
|
-
name: string;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export function changeAccountSubscriber(
|
|
19
|
-
params: ChangeAccountSubscriberParams
|
|
20
|
-
): [Subscriber<SuiActions>, SubscriberCleanUp<SuiActions>] {
|
|
21
|
-
let unsubscriber: () => void;
|
|
22
|
-
|
|
23
|
-
return [
|
|
24
|
-
(context, err) => {
|
|
25
|
-
const wallet = getInstanceOrThrow(params.name);
|
|
26
|
-
|
|
27
|
-
const [, setState] = context.state();
|
|
28
|
-
const eventCallback = (event: StandardEventsChangeProperties) => {
|
|
29
|
-
if (event.accounts) {
|
|
30
|
-
if (event.accounts.length === 0) {
|
|
31
|
-
context.action('disconnect');
|
|
32
|
-
} else {
|
|
33
|
-
setState(
|
|
34
|
-
'accounts',
|
|
35
|
-
event.accounts.map((account) => {
|
|
36
|
-
return AccountId.format({
|
|
37
|
-
address: account.address,
|
|
38
|
-
chainId: {
|
|
39
|
-
namespace: CAIP_NAMESPACE,
|
|
40
|
-
reference: CAIP_SUI_CHAIN_ID,
|
|
41
|
-
},
|
|
42
|
-
});
|
|
43
|
-
})
|
|
44
|
-
);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
};
|
|
48
|
-
unsubscriber = wallet.features['standard:events'].on(
|
|
49
|
-
'change',
|
|
50
|
-
eventCallback
|
|
51
|
-
);
|
|
52
|
-
|
|
53
|
-
if (err instanceof Error) {
|
|
54
|
-
throw err;
|
|
55
|
-
}
|
|
56
|
-
},
|
|
57
|
-
(_context, err) => {
|
|
58
|
-
if (unsubscriber) {
|
|
59
|
-
unsubscriber();
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
return err;
|
|
63
|
-
},
|
|
64
|
-
];
|
|
65
|
-
}
|
|
66
6
|
interface CanEagerConnectParams {
|
|
67
7
|
name: string;
|
|
68
8
|
}
|
|
@@ -1,7 +1,13 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
ChangeAccountSubscriberParams,
|
|
3
|
+
ProviderAPI,
|
|
4
|
+
SuiActions,
|
|
5
|
+
} from './types.js';
|
|
6
|
+
import type { WalletAccount } from '@mysten/wallet-standard';
|
|
2
7
|
|
|
3
8
|
import { ActionBuilder } from '../../mod.js';
|
|
4
9
|
import { CAIP } from '../../utils/mod.js';
|
|
10
|
+
import { ChangeAccountSubscriberBuilder } from '../common/hooks/changeAccountSubscriber.js';
|
|
5
11
|
import {
|
|
6
12
|
type CaipAccount,
|
|
7
13
|
connectAndUpdateStateForSingleNetwork,
|
|
@@ -10,8 +16,9 @@ import {
|
|
|
10
16
|
} from '../common/mod.js';
|
|
11
17
|
|
|
12
18
|
import { CAIP_NAMESPACE, CAIP_SUI_CHAIN_ID } from './constants.js';
|
|
13
|
-
import { getInstanceOrThrow } from './utils.js';
|
|
19
|
+
import { formatAccountsToCAIP, getInstanceOrThrow } from './utils.js';
|
|
14
20
|
|
|
21
|
+
// Actions
|
|
15
22
|
interface ConnectParams {
|
|
16
23
|
name: string;
|
|
17
24
|
}
|
|
@@ -42,3 +49,27 @@ export const connect = (params: ConnectParams) =>
|
|
|
42
49
|
|
|
43
50
|
export const canEagerConnect = () =>
|
|
44
51
|
new ActionBuilder<SuiActions, 'canEagerConnect'>('canEagerConnect');
|
|
52
|
+
|
|
53
|
+
// Hooks
|
|
54
|
+
export const changeAccountSubscriber = (
|
|
55
|
+
params: ChangeAccountSubscriberParams
|
|
56
|
+
) =>
|
|
57
|
+
new ChangeAccountSubscriberBuilder<
|
|
58
|
+
{ accounts: readonly WalletAccount[] },
|
|
59
|
+
ProviderAPI
|
|
60
|
+
>()
|
|
61
|
+
.getInstance(() => getInstanceOrThrow(params.name))
|
|
62
|
+
.validateEventPayload(
|
|
63
|
+
(event) =>
|
|
64
|
+
/*
|
|
65
|
+
* In some wallets, when a user switches to an account not yet connected to the dApp, it returns null.
|
|
66
|
+
* A null value indicates no access to the account, requiring a disconnect and user reconnection.
|
|
67
|
+
*/
|
|
68
|
+
|
|
69
|
+
event.accounts?.length !== 0
|
|
70
|
+
)
|
|
71
|
+
.format(async (_, event) => formatAccountsToCAIP(event.accounts))
|
|
72
|
+
.addEventListener((instance, callback) =>
|
|
73
|
+
instance.features['standard:events'].on('change', callback)
|
|
74
|
+
)
|
|
75
|
+
.removeEventListener((_, __) => {});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ChangeAccountSubscriberParams, SuiActions } from './types.js';
|
|
2
|
+
import type { Subscriber, SubscriberCleanUp } from '../../mod.js';
|
|
3
|
+
|
|
4
|
+
import { builders } from './mod.js';
|
|
5
|
+
|
|
6
|
+
export function changeAccountSubscriber(
|
|
7
|
+
params: ChangeAccountSubscriberParams
|
|
8
|
+
): [Subscriber<SuiActions>, SubscriberCleanUp<SuiActions>] {
|
|
9
|
+
return builders.changeAccountSubscriber({ name: params.name }).build();
|
|
10
|
+
}
|
|
@@ -2,6 +2,7 @@ export type { ProviderAPI, SuiActions } from './types.js';
|
|
|
2
2
|
|
|
3
3
|
export * as actions from './actions.js';
|
|
4
4
|
export * as builders from './builders.js';
|
|
5
|
+
export * as hooks from './hooks.js';
|
|
5
6
|
export { getInstanceOrThrow, getInstance } from './utils.js';
|
|
6
7
|
|
|
7
8
|
export { CAIP_NAMESPACE, CAIP_SUI_CHAIN_ID } from './constants.js';
|
|
@@ -3,6 +3,12 @@ import type {
|
|
|
3
3
|
AutoImplementedActionsByRecommended,
|
|
4
4
|
CommonActions,
|
|
5
5
|
} from '../common/types.js';
|
|
6
|
+
import type {
|
|
7
|
+
StandardConnectFeature,
|
|
8
|
+
StandardEventsFeature,
|
|
9
|
+
SuiFeatures,
|
|
10
|
+
WalletWithFeatures,
|
|
11
|
+
} from '@mysten/wallet-standard';
|
|
6
12
|
|
|
7
13
|
export interface SuiActions
|
|
8
14
|
extends AutoImplementedActionsByRecommended,
|
|
@@ -11,5 +17,10 @@ export interface SuiActions
|
|
|
11
17
|
canEagerConnect: () => Promise<boolean>;
|
|
12
18
|
}
|
|
13
19
|
|
|
14
|
-
|
|
15
|
-
|
|
20
|
+
export type ProviderAPI = WalletWithFeatures<
|
|
21
|
+
StandardConnectFeature & StandardEventsFeature & SuiFeatures
|
|
22
|
+
>;
|
|
23
|
+
|
|
24
|
+
export interface ChangeAccountSubscriberParams {
|
|
25
|
+
name: string;
|
|
26
|
+
}
|
|
@@ -6,6 +6,9 @@ import type {
|
|
|
6
6
|
} from '@mysten/wallet-standard';
|
|
7
7
|
|
|
8
8
|
import { getWallets, SUI_MAINNET_CHAIN } from '@mysten/wallet-standard';
|
|
9
|
+
import { AccountId } from 'caip';
|
|
10
|
+
|
|
11
|
+
import { CAIP_NAMESPACE, CAIP_SUI_CHAIN_ID } from './constants.js';
|
|
9
12
|
|
|
10
13
|
// TODO: StandardFetures doesn't work, so we should add each feature separately
|
|
11
14
|
type SuiWalletStandard = WalletWithFeatures<
|
|
@@ -40,3 +43,14 @@ export function getInstanceOrThrow(name: string): SuiWalletStandard {
|
|
|
40
43
|
|
|
41
44
|
return wallet;
|
|
42
45
|
}
|
|
46
|
+
export function formatAccountsToCAIP(accounts: readonly { address: string }[]) {
|
|
47
|
+
return accounts.map((account) => {
|
|
48
|
+
return AccountId.format({
|
|
49
|
+
address: account.address,
|
|
50
|
+
chainId: {
|
|
51
|
+
namespace: CAIP_NAMESPACE,
|
|
52
|
+
reference: CAIP_SUI_CHAIN_ID,
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
}
|