@dynamic-labs/embedded-wallet-solana 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.
Files changed (35) hide show
  1. package/CHANGELOG.md +3494 -0
  2. package/LICENSE +21 -0
  3. package/README.md +11 -0
  4. package/_virtual/_tslib.cjs +49 -0
  5. package/_virtual/_tslib.js +44 -0
  6. package/package.json +47 -0
  7. package/src/TurnkeySolanaWalletConnectors.cjs +19 -0
  8. package/src/TurnkeySolanaWalletConnectors.d.ts +2 -0
  9. package/src/TurnkeySolanaWalletConnectors.js +15 -0
  10. package/src/index.cjs +10 -0
  11. package/src/index.d.ts +2 -0
  12. package/src/index.js +2 -0
  13. package/src/lib/TurnkeySolanaWalletConnector/TurnkeySolanaSigner.cjs +60 -0
  14. package/src/lib/TurnkeySolanaWalletConnector/TurnkeySolanaSigner.d.ts +45 -0
  15. package/src/lib/TurnkeySolanaWalletConnector/TurnkeySolanaSigner.js +56 -0
  16. package/src/lib/TurnkeySolanaWalletConnector/TurnkeySolanaWalletConnector.cjs +323 -0
  17. package/src/lib/TurnkeySolanaWalletConnector/TurnkeySolanaWalletConnector.d.ts +55 -0
  18. package/src/lib/TurnkeySolanaWalletConnector/TurnkeySolanaWalletConnector.js +319 -0
  19. package/src/lib/TurnkeySolanaWalletConnector/index.d.ts +1 -0
  20. package/src/lib/constants.cjs +8 -0
  21. package/src/lib/constants.d.ts +1 -0
  22. package/src/lib/constants.js +4 -0
  23. package/src/lib/utils/createSolanaConnection/createSolanaConnection.cjs +14 -0
  24. package/src/lib/utils/createSolanaConnection/createSolanaConnection.d.ts +2 -0
  25. package/src/lib/utils/createSolanaConnection/createSolanaConnection.js +10 -0
  26. package/src/lib/utils/createSolanaConnection/index.d.ts +1 -0
  27. package/src/lib/utils/getGenesisHashLSKey/getGenesisHashLSKey.cjs +10 -0
  28. package/src/lib/utils/getGenesisHashLSKey/getGenesisHashLSKey.d.ts +1 -0
  29. package/src/lib/utils/getGenesisHashLSKey/getGenesisHashLSKey.js +6 -0
  30. package/src/lib/utils/getGenesisHashLSKey/index.d.ts +1 -0
  31. package/src/lib/utils/index.d.ts +3 -0
  32. package/src/lib/utils/transactionDecoder/index.d.ts +1 -0
  33. package/src/lib/utils/transactionDecoder/transactionDecoder.cjs +106 -0
  34. package/src/lib/utils/transactionDecoder/transactionDecoder.d.ts +10 -0
  35. package/src/lib/utils/transactionDecoder/transactionDecoder.js +101 -0
@@ -0,0 +1,323 @@
1
+ 'use client'
2
+ 'use strict';
3
+
4
+ Object.defineProperty(exports, '__esModule', { value: true });
5
+
6
+ var _tslib = require('../../../_virtual/_tslib.cjs');
7
+ var web3_js = require('@solana/web3.js');
8
+ var webauthnStamper = require('@turnkey/webauthn-stamper');
9
+ var http = require('@turnkey/http');
10
+ var solana = require('@turnkey/solana');
11
+ var iframeStamper = require('@turnkey/iframe-stamper');
12
+ var rpcProviderSolana = require('@dynamic-labs/rpc-provider-solana');
13
+ var utils = require('@dynamic-labs/utils');
14
+ var solanaUtils = require('@dynamic-labs/solana-utils');
15
+ var embeddedWallet = require('@dynamic-labs/embedded-wallet');
16
+ var createSolanaConnection = require('../utils/createSolanaConnection/createSolanaConnection.cjs');
17
+ var getGenesisHashLSKey = require('../utils/getGenesisHashLSKey/getGenesisHashLSKey.cjs');
18
+ var transactionDecoder = require('../utils/transactionDecoder/transactionDecoder.cjs');
19
+ var TurnkeySolanaSigner = require('./TurnkeySolanaSigner.cjs');
20
+
21
+ class TurnkeySolanaWalletConnector extends embeddedWallet.TurnkeyWalletConnectorBase {
22
+ constructor(nameAndKey, props) {
23
+ var _a;
24
+ super(nameAndKey, props);
25
+ // Public fields
26
+ this.connectedChain = 'SOL';
27
+ this.supportedChains = ['SOL'];
28
+ this.verifiedCredentialChain = 'solana';
29
+ this.solNetworks = props.solNetworks;
30
+ this.walletUiUtils = props.walletUiUtils;
31
+ this._turnkeyAccount = undefined;
32
+ this._connectionClient = undefined;
33
+ this.chainRpcProviders = props.chainRpcProviders;
34
+ (_a = this.chainRpcProviders) === null || _a === void 0 ? void 0 : _a.registerSolanaProviders();
35
+ this.__turnkeyClient = this.getTurnkeyClient();
36
+ }
37
+ getRpcUrl() {
38
+ var _a;
39
+ const [network] = this.solNetworks;
40
+ if (!network) {
41
+ throw new utils.DynamicError('No enabled networks');
42
+ }
43
+ return ((_a = network.privateCustomerRpcUrls) === null || _a === void 0 ? void 0 : _a[0]) || network.rpcUrls[0];
44
+ }
45
+ getConnection(commitmentOrConfig) {
46
+ if (!this._connectionClient) {
47
+ const rpcUrl = this.getRpcUrl();
48
+ if (!rpcUrl)
49
+ throw new utils.DynamicError('No rpcUrl');
50
+ this._connectionClient = createSolanaConnection.createSolanaConnection(rpcUrl, commitmentOrConfig);
51
+ }
52
+ return this._connectionClient;
53
+ }
54
+ getWalletClient() {
55
+ return this.getConnection();
56
+ }
57
+ getNetwork() {
58
+ return _tslib.__awaiter(this, void 0, void 0, function* () {
59
+ const connection = this.getConnection();
60
+ let genesisHash = localStorage.getItem(getGenesisHashLSKey.getGenesisHashLSKey(connection.rpcEndpoint));
61
+ if (!genesisHash) {
62
+ genesisHash = yield connection.getGenesisHash();
63
+ localStorage.setItem(getGenesisHashLSKey.getGenesisHashLSKey(connection.rpcEndpoint), genesisHash);
64
+ }
65
+ genesisHash = genesisHash.substring(0, 32);
66
+ // see: https://github.com/ChainAgnostic/namespaces/blob/main/solana/caip2.md
67
+ if (genesisHash === '5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp') {
68
+ return 'mainnet';
69
+ }
70
+ else if (genesisHash === 'EtWTRABZaYq6iMfeYKouRu166VU2xqa1') {
71
+ return 'devnet';
72
+ }
73
+ else {
74
+ return 'testnet';
75
+ }
76
+ });
77
+ }
78
+ getPublicClient() {
79
+ return _tslib.__awaiter(this, void 0, void 0, function* () {
80
+ var _a;
81
+ if (this.solNetworks.length === 0)
82
+ return;
83
+ const configurations = {
84
+ cosmos: [],
85
+ evm: undefined,
86
+ solana: this.solNetworks,
87
+ starknet: undefined,
88
+ };
89
+ if (!this.chainRpcProviders)
90
+ return undefined;
91
+ const providers = this.chainRpcProviders.getProviders(configurations);
92
+ return (_a = this.chainRpcProviders.getSolanaProviderByChainId(providers, '101')) === null || _a === void 0 ? void 0 : _a.provider;
93
+ });
94
+ }
95
+ supportsNetworkSwitching() {
96
+ return false;
97
+ }
98
+ setVerifiedCredentials(verifiedCredentials) {
99
+ const turnkeyVerifiedCredential = embeddedWallet.findTurnkeyVerifiedCredential(verifiedCredentials, rpcProviderSolana.ProviderChain.SOLANA);
100
+ const didTurnkeyVerifiedCredentialsChanged = JSON.stringify(this.verifiedCredential) !==
101
+ JSON.stringify(turnkeyVerifiedCredential);
102
+ if (!didTurnkeyVerifiedCredentialsChanged) {
103
+ return;
104
+ }
105
+ this.verifiedCredential = turnkeyVerifiedCredential;
106
+ this.refreshTurnkeyAccount();
107
+ }
108
+ getAccount() {
109
+ return this.turnkeyAddress;
110
+ }
111
+ endSession() {
112
+ return _tslib.__awaiter(this, void 0, void 0, function* () {
113
+ localStorage.removeItem(getGenesisHashLSKey.getGenesisHashLSKey(this.getRpcUrl()));
114
+ });
115
+ }
116
+ refreshTurnkeyAccount() {
117
+ return _tslib.__awaiter(this, void 0, void 0, function* () {
118
+ this._turnkeyAccount = undefined;
119
+ return this.getTurnkeyAccount();
120
+ });
121
+ }
122
+ getTurnkeyClient() {
123
+ var _a;
124
+ let rpId = utils.getTLD();
125
+ if (!rpId) {
126
+ rpId = utils.PlatformService.getHostname();
127
+ }
128
+ const passkeyStamper = embeddedWallet.PasskeyService.createWebauthnStamper({
129
+ rpId,
130
+ });
131
+ const apiKeyStamper = embeddedWallet.TurnkeyWalletConnectorBase === null || embeddedWallet.TurnkeyWalletConnectorBase === void 0 ? void 0 : embeddedWallet.TurnkeyWalletConnectorBase.apiKeyStamper;
132
+ const stamper = apiKeyStamper !== null && apiKeyStamper !== void 0 ? apiKeyStamper : passkeyStamper;
133
+ this.__turnkeyClient =
134
+ (_a = this.getAuthenticatorHandler().client) !== null && _a !== void 0 ? _a : new http.TurnkeyClient({
135
+ baseUrl: embeddedWallet.TURNKEY_API_BASE_URL,
136
+ }, stamper);
137
+ return this.__turnkeyClient;
138
+ }
139
+ createTurnkeyAccount(_a) {
140
+ return _tslib.__awaiter(this, arguments, void 0, function* ({ organizationId, }) {
141
+ const turnkeyClient = this.getTurnkeyClient();
142
+ const signer = new solana.TurnkeySigner({ client: turnkeyClient, organizationId });
143
+ return signer;
144
+ });
145
+ }
146
+ getTurnkeyAccount() {
147
+ return _tslib.__awaiter(this, void 0, void 0, function* () {
148
+ var _a, _b, _c, _d;
149
+ if (this._turnkeyAccount &&
150
+ ((this.getAuthenticatorHandler().recoveryType === 'passkey' &&
151
+ ((_a = this.__turnkeyClient) === null || _a === void 0 ? void 0 : _a.stamper) instanceof webauthnStamper.WebauthnStamper) ||
152
+ (this.getAuthenticatorHandler().recoveryType === 'email' &&
153
+ ((_b = this.__turnkeyClient) === null || _b === void 0 ? void 0 : _b.stamper) instanceof iframeStamper.IframeStamper)) &&
154
+ this.__turnkeyClient === this.getAuthenticatorHandler().client) {
155
+ return this._turnkeyAccount;
156
+ }
157
+ const { turnkeySubOrganizationId } = (_c = this.walletProperties) !== null && _c !== void 0 ? _c : {};
158
+ const { address } = (_d = this.verifiedCredential) !== null && _d !== void 0 ? _d : {};
159
+ if (!turnkeySubOrganizationId || !address) {
160
+ return;
161
+ }
162
+ this._turnkeyAccount = yield this.createTurnkeyAccount({
163
+ organizationId: turnkeySubOrganizationId,
164
+ });
165
+ return this._turnkeyAccount;
166
+ });
167
+ }
168
+ getSigner() {
169
+ return _tslib.__awaiter(this, void 0, void 0, function* () {
170
+ if (this.isSessionKeyCompatible()) {
171
+ yield this.createOrRestoreSession();
172
+ }
173
+ return new TurnkeySolanaSigner.TurnkeySolanaSigner({ walletConnector: this });
174
+ });
175
+ }
176
+ getBalance() {
177
+ return _tslib.__awaiter(this, void 0, void 0, function* () {
178
+ const address = this.getAccount();
179
+ if (!address) {
180
+ return undefined;
181
+ }
182
+ const connectionClient = this.getConnection();
183
+ const publicKey = new web3_js.PublicKey(address);
184
+ const balance = yield connectionClient.getBalance(publicKey);
185
+ const solBalance = this.lamportsToSol(balance);
186
+ return solBalance.toString();
187
+ });
188
+ }
189
+ signMessage(messageToSign) {
190
+ return _tslib.__awaiter(this, void 0, void 0, function* () {
191
+ if (!this.turnkeyAddress) {
192
+ throw new utils.DynamicError('No turnkey account');
193
+ }
194
+ const address = this.turnkeyAddress;
195
+ const signedMessage = yield this.walletUiUtils.signMessage({
196
+ handler: () => _tslib.__awaiter(this, void 0, void 0, function* () {
197
+ var _a;
198
+ const enc = new TextEncoder();
199
+ const encodedMessage = enc.encode(messageToSign);
200
+ const signedMessageRaw = yield ((_a = (yield this.getTurnkeyAccount())) === null || _a === void 0 ? void 0 : _a.signMessage(encodedMessage, address));
201
+ return utils.bufferToBase64(signedMessageRaw || Buffer.from([]));
202
+ }),
203
+ message: messageToSign,
204
+ });
205
+ return signedMessage;
206
+ });
207
+ }
208
+ signTransaction(_a) {
209
+ return _tslib.__awaiter(this, arguments, void 0, function* ({ transaction, }) {
210
+ const account = yield this.getTurnkeyAccount();
211
+ const address = this.turnkeyAddress;
212
+ if (!account || !address) {
213
+ throw new Error('No turnkey account');
214
+ }
215
+ yield account.addSignature(transaction, address);
216
+ return Buffer.from(transaction.serialize());
217
+ });
218
+ }
219
+ internalSignAndSendTransaction(transaction, options) {
220
+ return _tslib.__awaiter(this, void 0, void 0, function* () {
221
+ var _a;
222
+ if (!this.turnkeyAddress)
223
+ throw new utils.DynamicError('Solana wallet not found');
224
+ const currentConnection = this.getConnection('confirmed');
225
+ const blockhash = yield currentConnection.getLatestBlockhash();
226
+ if ('version' in transaction) {
227
+ transaction.message.recentBlockhash =
228
+ blockhash.blockhash;
229
+ }
230
+ else {
231
+ transaction.recentBlockhash = blockhash.blockhash;
232
+ transaction.feePayer =
233
+ (_a = transaction.feePayer) !== null && _a !== void 0 ? _a : new web3_js.PublicKey(this.turnkeyAddress);
234
+ }
235
+ const signedTransaction = yield this.signTransaction({ transaction });
236
+ const signature = yield currentConnection.sendRawTransaction(signedTransaction, options);
237
+ // listen for tx confirmation until 60 seconds, which is ~150 blocks expiration
238
+ return new Promise((resolve, reject) => {
239
+ const timeout = setTimeout(() => {
240
+ reject(new utils.DynamicError('Transaction timed out'));
241
+ }, 60000);
242
+ currentConnection.onSignature(signature, (result) => {
243
+ clearTimeout(timeout);
244
+ if (result.err) {
245
+ reject(new utils.DynamicError('Transaction failed'));
246
+ }
247
+ else {
248
+ resolve(signature);
249
+ }
250
+ }, 'confirmed');
251
+ });
252
+ });
253
+ }
254
+ signAndSendTransaction(transaction, options) {
255
+ return _tslib.__awaiter(this, void 0, void 0, function* () {
256
+ if (!this.turnkeyAddress)
257
+ throw new utils.DynamicError('Solana wallet not found');
258
+ const transactionsData = yield transactionDecoder.decodeTransaction(transaction, this.getConnection(), this.turnkeyAddress);
259
+ if (!(transactionsData === null || transactionsData === void 0 ? void 0 : transactionsData.length)) {
260
+ throw new utils.DynamicError('Incorrectly formatted transaction instructions');
261
+ }
262
+ const { to, value } = transactionDecoder.summarizeTransactionDecodedData(transactionsData);
263
+ const uiTransaction = new solanaUtils.SolanaUiTransaction({
264
+ connection: this.getConnection(),
265
+ from: this.turnkeyAddress,
266
+ onSubmit: () => _tslib.__awaiter(this, void 0, void 0, function* () { return this.internalSignAndSendTransaction(transaction, options); }),
267
+ originalTransaction: transaction,
268
+ });
269
+ uiTransaction.to = to;
270
+ uiTransaction.value = value;
271
+ return this.walletUiUtils.sendTransaction(this, uiTransaction);
272
+ });
273
+ }
274
+ sendTransaction(transaction_1, connection_1) {
275
+ return _tslib.__awaiter(this, arguments, void 0, function* (transaction, connection, options = {}) {
276
+ var _a;
277
+ if (!this.turnkeyAddress)
278
+ throw new utils.DynamicError('Solana wallet not found');
279
+ if (!transaction || !connection) {
280
+ throw new utils.DynamicError('Transaction and connection are required');
281
+ }
282
+ const { signers } = options, sendOptions = _tslib.__rest(options, ["signers"]);
283
+ const blockhash = yield connection.getLatestBlockhash({
284
+ commitment: options.preflightCommitment,
285
+ minContextSlot: options.minContextSlot,
286
+ });
287
+ if ('version' in transaction) {
288
+ (signers === null || signers === void 0 ? void 0 : signers.length) && transaction.sign(signers);
289
+ }
290
+ else {
291
+ transaction.feePayer =
292
+ transaction.feePayer || new web3_js.PublicKey(this.turnkeyAddress);
293
+ transaction.recentBlockhash =
294
+ transaction.recentBlockhash || blockhash.blockhash;
295
+ (signers === null || signers === void 0 ? void 0 : signers.length) && transaction.partialSign(...signers);
296
+ }
297
+ sendOptions.preflightCommitment =
298
+ sendOptions.preflightCommitment || connection.commitment;
299
+ const signature = yield connection.sendRawTransaction(transaction.serialize(), options);
300
+ const transactionConfirmationStrategy = {
301
+ blockhash: blockhash.blockhash,
302
+ lastValidBlockHeight: blockhash.lastValidBlockHeight,
303
+ signature,
304
+ };
305
+ const result = yield (connection === null || connection === void 0 ? void 0 : connection.confirmTransaction(transactionConfirmationStrategy));
306
+ return ((_a = result === null || result === void 0 ? void 0 : result.value) === null || _a === void 0 ? void 0 : _a.err) ? JSON.stringify(result.value.err) : signature;
307
+ });
308
+ }
309
+ lamportsToSol(lamports) {
310
+ return lamports / web3_js.LAMPORTS_PER_SOL;
311
+ }
312
+ createUiTransaction(from) {
313
+ return _tslib.__awaiter(this, void 0, void 0, function* () {
314
+ return new solanaUtils.SolanaUiTransaction({
315
+ connection: this.getConnection(),
316
+ from,
317
+ onSubmit: (transaction) => _tslib.__awaiter(this, void 0, void 0, function* () { return this.internalSignAndSendTransaction(transaction); }),
318
+ });
319
+ });
320
+ }
321
+ }
322
+
323
+ exports.TurnkeySolanaWalletConnector = TurnkeySolanaWalletConnector;
@@ -0,0 +1,55 @@
1
+ /// <reference types="node" />
2
+ import { Commitment, Connection, ConnectionConfig, Transaction, VersionedTransaction, ConfirmOptions, Signer, SendOptions } from '@solana/web3.js';
3
+ import { GenericNetwork, IUITransaction, WalletUiUtils } from '@dynamic-labs/types';
4
+ import { Chain, ISendBalanceWalletConnector, WalletConnector } from '@dynamic-labs/wallet-connector-core';
5
+ import { WalletBookSchema } from '@dynamic-labs/wallet-book';
6
+ import { JwtVerifiedCredential } from '@dynamic-labs/sdk-api-core';
7
+ import { IChainRpcProviders } from '@dynamic-labs/rpc-provider-solana';
8
+ import { TurnkeyWalletConnectorBase, TurnkeyWalletConnectorNameAndKey } from '@dynamic-labs/embedded-wallet';
9
+ import { TurnkeySolanaSigner } from './TurnkeySolanaSigner';
10
+ type SendTransactionOptions = ConfirmOptions & {
11
+ signers?: Signer[];
12
+ };
13
+ export type TurnkeySolanaConnectorProps = {
14
+ walletUiUtils: WalletUiUtils<WalletConnector>;
15
+ walletBook: WalletBookSchema;
16
+ solNetworks: GenericNetwork[];
17
+ appName?: string;
18
+ chainRpcProviders: IChainRpcProviders;
19
+ };
20
+ export declare class TurnkeySolanaWalletConnector extends TurnkeyWalletConnectorBase implements ISendBalanceWalletConnector {
21
+ connectedChain: Chain;
22
+ supportedChains: Chain[];
23
+ solNetworks: GenericNetwork[];
24
+ verifiedCredentialChain: string;
25
+ private walletUiUtils;
26
+ private _turnkeyAccount;
27
+ private _connectionClient;
28
+ private __turnkeyClient;
29
+ constructor(nameAndKey: TurnkeyWalletConnectorNameAndKey, props: TurnkeySolanaConnectorProps);
30
+ getRpcUrl(): string;
31
+ getConnection(commitmentOrConfig?: Commitment | ConnectionConfig): Connection;
32
+ getWalletClient(): Connection;
33
+ getNetwork(): Promise<string>;
34
+ getPublicClient(): Promise<Connection | undefined>;
35
+ supportsNetworkSwitching(): boolean;
36
+ setVerifiedCredentials(verifiedCredentials: JwtVerifiedCredential[]): void;
37
+ getAccount(): string | undefined;
38
+ endSession(): Promise<void>;
39
+ private refreshTurnkeyAccount;
40
+ private getTurnkeyClient;
41
+ private createTurnkeyAccount;
42
+ private getTurnkeyAccount;
43
+ getSigner(): Promise<TurnkeySolanaSigner | undefined>;
44
+ getBalance(): Promise<string | undefined>;
45
+ signMessage(messageToSign: string): Promise<string | undefined>;
46
+ signTransaction({ transaction, }: {
47
+ transaction: Transaction | VersionedTransaction;
48
+ }): Promise<Buffer>;
49
+ internalSignAndSendTransaction(transaction: Transaction | VersionedTransaction, options?: SendOptions): Promise<string>;
50
+ signAndSendTransaction(transaction: Transaction | VersionedTransaction, options?: SendOptions): Promise<string>;
51
+ sendTransaction(transaction: Transaction | VersionedTransaction, connection: Connection, options?: SendTransactionOptions): Promise<string>;
52
+ private lamportsToSol;
53
+ createUiTransaction(from: string): Promise<IUITransaction>;
54
+ }
55
+ export {};