@dynamic-labs/embedded-wallet-evm 3.0.0-alpha.8

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.
@@ -0,0 +1,283 @@
1
+ 'use client'
2
+ import { __awaiter } from '../../../_virtual/_tslib.js';
3
+ import { ApiKeyStamper } from '@turnkey/api-key-stamper';
4
+ import { TurnkeyClient } from '@turnkey/http';
5
+ import { IframeStamper } from '@turnkey/iframe-stamper';
6
+ import { createAccount } from '@turnkey/viem';
7
+ import { WebauthnStamper } from '@turnkey/webauthn-stamper';
8
+ import { http, createPublicClient, formatEther } from 'viem';
9
+ import { parseEvmNetworks, getTLD, PlatformService, DynamicError } from '@dynamic-labs/utils';
10
+ import { createWalletClientWithUiConfirmation, getOrMapViemChain, createViemUiTransaction } from '@dynamic-labs/viem-utils';
11
+ import { getRpcUrlForChain, logger } from '@dynamic-labs/wallet-connector-core';
12
+ import { TurnkeyWalletConnectorBase, findTurnkeyVerifiedCredential, PasskeyService, TURNKEY_API_BASE_URL } from '@dynamic-labs/embedded-wallet';
13
+
14
+ class TurnkeyEVMWalletConnector extends TurnkeyWalletConnectorBase {
15
+ constructor(nameAndKey, props) {
16
+ var _a;
17
+ super(nameAndKey, props);
18
+ this.walletFallback = {
19
+ brand: {
20
+ alt: 'Turnkey Wallet',
21
+ spriteId: 'turnkey',
22
+ },
23
+ name: 'Turnkey HD',
24
+ };
25
+ // Public fields
26
+ this.connectedChain = 'EVM';
27
+ this.supportedChains = ['ETH', 'EVM'];
28
+ this.verifiedCredentialChain = 'eip155';
29
+ this.evmNetworks = parseEvmNetworks(props.evmNetworks);
30
+ this.walletUiUtils = props.walletUiUtils;
31
+ this._turnkeyAccount = undefined;
32
+ this._selectedChainId = this.getLastUsedChainId();
33
+ this.chainRpcProviders = props.chainRpcProviders;
34
+ (_a = this.chainRpcProviders) === null || _a === void 0 ? void 0 : _a.registerEvmProviders();
35
+ this.__turnkeyClient = this.getTurnkeyClient();
36
+ }
37
+ getLastUsedChainId() {
38
+ var _a;
39
+ if (this.lastUsedChainId) {
40
+ return this.lastUsedChainId;
41
+ }
42
+ if (!((_a = this.evmNetworks) === null || _a === void 0 ? void 0 : _a.length)) {
43
+ return undefined;
44
+ }
45
+ return this.evmNetworks[0].chainId;
46
+ }
47
+ // Public methods
48
+ getNetwork() {
49
+ return __awaiter(this, void 0, void 0, function* () {
50
+ var _a;
51
+ return (_a = (yield this.getSigner())) === null || _a === void 0 ? void 0 : _a.getChainId();
52
+ });
53
+ }
54
+ supportsNetworkSwitching() {
55
+ return true;
56
+ }
57
+ switchNetwork(_a) {
58
+ return __awaiter(this, arguments, void 0, function* ({ networkChainId, }) {
59
+ this.lastUsedChainId = networkChainId;
60
+ this._selectedChainId = networkChainId;
61
+ yield this.refreshTurnkeyAccount();
62
+ this.emit('chainChange', {
63
+ chain: networkChainId.toString(),
64
+ });
65
+ });
66
+ }
67
+ setVerifiedCredentials(verifiedCredentials) {
68
+ const turnkeyVerifiedCredential = findTurnkeyVerifiedCredential(verifiedCredentials, 'eip155');
69
+ const didTurnkeyVerifiedCredentialsChanged = JSON.stringify(this.verifiedCredential) !==
70
+ JSON.stringify(turnkeyVerifiedCredential);
71
+ if (!didTurnkeyVerifiedCredentialsChanged) {
72
+ return;
73
+ }
74
+ this.verifiedCredential = turnkeyVerifiedCredential;
75
+ this.refreshTurnkeyAccount();
76
+ }
77
+ getRpcUrl() {
78
+ const chain = this._selectedChainId;
79
+ return getRpcUrlForChain({
80
+ chainId: chain,
81
+ networks: this.evmNetworks,
82
+ });
83
+ }
84
+ getBalance() {
85
+ return __awaiter(this, void 0, void 0, function* () {
86
+ const address = this.turnkeyAddress;
87
+ if (!address) {
88
+ return undefined;
89
+ }
90
+ const rpcUrl = this.getRpcUrl();
91
+ if (!rpcUrl) {
92
+ return undefined;
93
+ }
94
+ const client = createPublicClient({
95
+ transport: http(rpcUrl),
96
+ });
97
+ const balance = yield client.getBalance({
98
+ address: address,
99
+ });
100
+ return formatEther(balance);
101
+ });
102
+ }
103
+ signMessage(messageToSign) {
104
+ return __awaiter(this, void 0, void 0, function* () {
105
+ const signer = yield this.getSigner();
106
+ if (!signer) {
107
+ throw new Error('Signer not found');
108
+ }
109
+ return signer.signMessage({
110
+ message: messageToSign,
111
+ });
112
+ });
113
+ }
114
+ getPublicClient() {
115
+ return __awaiter(this, void 0, void 0, function* () {
116
+ var _a, _b;
117
+ if (this.evmNetworks.length === 0) {
118
+ return undefined;
119
+ }
120
+ const networkId = (_a = (yield this.getNetwork())) !== null && _a !== void 0 ? _a : 1;
121
+ const configurations = {
122
+ cosmos: [],
123
+ evm: this.evmNetworks,
124
+ solana: [],
125
+ starknet: undefined,
126
+ };
127
+ if (!this.chainRpcProviders)
128
+ return undefined;
129
+ const providers = this.chainRpcProviders.getProviders(configurations);
130
+ return (_b = this.chainRpcProviders.getEvmProviderByChainId(providers, networkId)) === null || _b === void 0 ? void 0 : _b.provider;
131
+ });
132
+ }
133
+ getSigner() {
134
+ return __awaiter(this, void 0, void 0, function* () {
135
+ if (this.isSessionKeyCompatible()) {
136
+ yield this.createOrRestoreSession();
137
+ }
138
+ yield this.getTurnkeyAccount();
139
+ return this.getWalletClient();
140
+ });
141
+ }
142
+ getTurnkeyClient() {
143
+ var _a;
144
+ let rpId = getTLD();
145
+ if (!rpId) {
146
+ rpId = PlatformService.getHostname();
147
+ }
148
+ const passkeyStamper = PasskeyService.createWebauthnStamper({
149
+ rpId,
150
+ });
151
+ const apiKeyStamper = TurnkeyWalletConnectorBase === null || TurnkeyWalletConnectorBase === void 0 ? void 0 : TurnkeyWalletConnectorBase.apiKeyStamper;
152
+ const stamper = apiKeyStamper !== null && apiKeyStamper !== void 0 ? apiKeyStamper : passkeyStamper;
153
+ this.__turnkeyClient =
154
+ (_a = this.getAuthenticatorHandler().client) !== null && _a !== void 0 ? _a : new TurnkeyClient({
155
+ baseUrl: TURNKEY_API_BASE_URL,
156
+ }, stamper);
157
+ return this.__turnkeyClient;
158
+ }
159
+ // decides in runtime which stamper to use and creates the corresponding account
160
+ getAccount() {
161
+ return __awaiter(this, void 0, void 0, function* () {
162
+ var _a, _b, _c;
163
+ if (this.isSessionKeyCompatible() &&
164
+ ((_a = this.__turnkeyClient) === null || _a === void 0 ? void 0 : _a.stamper) instanceof ApiKeyStamper) {
165
+ return this._turnkeyAccount;
166
+ }
167
+ if ((this.getAuthenticatorHandler().recoveryType === 'passkey' &&
168
+ ((_b = this.__turnkeyClient) === null || _b === void 0 ? void 0 : _b.stamper) instanceof IframeStamper) ||
169
+ (this.getAuthenticatorHandler().recoveryType === 'email' &&
170
+ ((_c = this.__turnkeyClient) === null || _c === void 0 ? void 0 : _c.stamper) instanceof WebauthnStamper) ||
171
+ this.__turnkeyClient !== this.getAuthenticatorHandler().client) {
172
+ yield this.refreshTurnkeyAccount();
173
+ }
174
+ return this._turnkeyAccount;
175
+ });
176
+ }
177
+ getWalletClient() {
178
+ const rpcUrl = this.networkRpcUrl;
179
+ const account = this._turnkeyAccount;
180
+ const evmNetwork = this.currentEvmNetwork;
181
+ if (!account || !rpcUrl || !evmNetwork) {
182
+ return undefined;
183
+ }
184
+ return createWalletClientWithUiConfirmation({
185
+ account: this.getAccount.bind(this),
186
+ address: this.turnkeyAddress,
187
+ chain: getOrMapViemChain(evmNetwork),
188
+ transport: http(rpcUrl),
189
+ walletConnector: this,
190
+ walletUiUtils: this.walletUiUtils,
191
+ });
192
+ }
193
+ // Private methods
194
+ refreshTurnkeyAccount() {
195
+ return __awaiter(this, void 0, void 0, function* () {
196
+ this._turnkeyAccount = undefined;
197
+ return this.getTurnkeyAccount();
198
+ });
199
+ }
200
+ get currentChainId() {
201
+ var _a, _b, _c;
202
+ return (_a = this._selectedChainId) !== null && _a !== void 0 ? _a : (_c = (_b = this.evmNetworks) === null || _b === void 0 ? void 0 : _b[0]) === null || _c === void 0 ? void 0 : _c.chainId;
203
+ }
204
+ get networkRpcUrl() {
205
+ const chainId = this.currentChainId;
206
+ const evmNetwork = this.evmNetworks.find((network) => network.chainId === chainId);
207
+ if (!evmNetwork) {
208
+ return undefined;
209
+ }
210
+ const rpcUrl = getRpcUrlForChain({
211
+ chainId: chainId,
212
+ networks: this.evmNetworks,
213
+ });
214
+ return rpcUrl;
215
+ }
216
+ get currentEvmNetwork() {
217
+ const chainId = this.currentChainId;
218
+ return this.evmNetworks.find((network) => network.chainId === chainId);
219
+ }
220
+ getTurnkeyAccount() {
221
+ return __awaiter(this, void 0, void 0, function* () {
222
+ var _a, _b;
223
+ if (this._turnkeyAccount) {
224
+ return this._turnkeyAccount;
225
+ }
226
+ const { turnkeySubOrganizationId } = (_a = this.walletProperties) !== null && _a !== void 0 ? _a : {};
227
+ const { address } = (_b = this.verifiedCredential) !== null && _b !== void 0 ? _b : {};
228
+ if (!turnkeySubOrganizationId || !address) {
229
+ return;
230
+ }
231
+ this._turnkeyAccount = yield createAccount({
232
+ client: this.getTurnkeyClient(),
233
+ ethereumAddress: address,
234
+ organizationId: turnkeySubOrganizationId,
235
+ signWith: address,
236
+ });
237
+ return this._turnkeyAccount;
238
+ });
239
+ }
240
+ get lastUsedChainId() {
241
+ const lastUsedChainIdLS = localStorage.getItem(TurnkeyEVMWalletConnector.lastUsedChainIdStorageKey);
242
+ if (!lastUsedChainIdLS)
243
+ return undefined;
244
+ try {
245
+ const chainId = parseInt(lastUsedChainIdLS);
246
+ if (isNaN(chainId)) {
247
+ return undefined;
248
+ }
249
+ const isChainCurrentlyEnabled = this.evmNetworks.some((network) => network.chainId === chainId);
250
+ if (!isChainCurrentlyEnabled) {
251
+ const lastUsedChainId = this.evmNetworks[0].chainId;
252
+ this.lastUsedChainId = lastUsedChainId;
253
+ return this.lastUsedChainId;
254
+ }
255
+ return chainId;
256
+ }
257
+ catch (err) {
258
+ logger.error(err);
259
+ return undefined;
260
+ }
261
+ }
262
+ set lastUsedChainId(chainId) {
263
+ if (chainId === undefined) {
264
+ localStorage.removeItem(TurnkeyEVMWalletConnector.lastUsedChainIdStorageKey);
265
+ }
266
+ else {
267
+ localStorage.setItem(TurnkeyEVMWalletConnector.lastUsedChainIdStorageKey, chainId.toString());
268
+ }
269
+ }
270
+ createUiTransaction(from) {
271
+ return __awaiter(this, void 0, void 0, function* () {
272
+ const walletClient = this.getWalletClient();
273
+ const publicClient = yield this.getPublicClient();
274
+ if (!publicClient || !walletClient) {
275
+ throw new DynamicError('No public client available');
276
+ }
277
+ return createViemUiTransaction({ from, publicClient, walletClient });
278
+ });
279
+ }
280
+ }
281
+ TurnkeyEVMWalletConnector.lastUsedChainIdStorageKey = 'turnkey-last-used-chain-id';
282
+
283
+ export { TurnkeyEVMWalletConnector };
@@ -0,0 +1 @@
1
+ export * from './TurnkeyEVMWalletConnector';