@dynamic-labs/embedded-wallet-solana 4.0.0-alpha.5 → 4.0.0-alpha.51
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 +468 -0
- package/package.cjs +6 -8
- package/package.js +6 -8
- package/package.json +15 -24
- package/src/TurnkeySolanaWalletConnectors.cjs +5 -1
- package/src/TurnkeySolanaWalletConnectors.js +5 -1
- package/src/index.cjs +3 -1
- package/src/index.js +4 -0
- package/src/lib/TurnkeySolanaWalletConnector/TurnkeySolanaSigner.cjs +2 -4
- package/src/lib/TurnkeySolanaWalletConnector/TurnkeySolanaSigner.d.ts +1 -1
- package/src/lib/TurnkeySolanaWalletConnector/TurnkeySolanaSigner.js +2 -4
- package/src/lib/TurnkeySolanaWalletConnector/TurnkeySolanaWalletConnector.cjs +97 -85
- package/src/lib/TurnkeySolanaWalletConnector/TurnkeySolanaWalletConnector.d.ts +7 -7
- package/src/lib/TurnkeySolanaWalletConnector/TurnkeySolanaWalletConnector.js +100 -88
- package/src/lib/utils/index.d.ts +0 -1
- package/src/lib/utils/transactionDecoder/index.d.ts +0 -1
- package/src/lib/utils/transactionDecoder/transactionDecoder.cjs +0 -162
- package/src/lib/utils/transactionDecoder/transactionDecoder.d.ts +0 -12
- package/src/lib/utils/transactionDecoder/transactionDecoder.js +0 -156
package/src/index.js
CHANGED
|
@@ -1,2 +1,6 @@
|
|
|
1
1
|
'use client'
|
|
2
|
+
import { assertPackageVersion } from '@dynamic-labs/assert-package-version';
|
|
3
|
+
import { version } from '../package.js';
|
|
2
4
|
export { TurnkeySolanaWalletConnectors } from './TurnkeySolanaWalletConnectors.js';
|
|
5
|
+
|
|
6
|
+
assertPackageVersion('@dynamic-labs/embedded-wallet-solana', version);
|
|
@@ -27,11 +27,9 @@ class TurnkeySolanaSigner {
|
|
|
27
27
|
return this.walletConnector.signTransaction(transaction);
|
|
28
28
|
});
|
|
29
29
|
}
|
|
30
|
-
signAllTransactions(
|
|
31
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
32
|
-
_transactions) {
|
|
30
|
+
signAllTransactions(transactions) {
|
|
33
31
|
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
34
|
-
|
|
32
|
+
return this.walletConnector.signAllTransactions(transactions);
|
|
35
33
|
});
|
|
36
34
|
}
|
|
37
35
|
signAndSendTransaction(transaction, options) {
|
|
@@ -32,7 +32,7 @@ export declare class TurnkeySolanaSigner implements IEmbeddedWalletSolanaSigner
|
|
|
32
32
|
});
|
|
33
33
|
signMessage(encodedMessage: Uint8Array): Promise<SignedMessage>;
|
|
34
34
|
signTransaction<T extends Transaction | VersionedTransaction>(transaction: T): Promise<T>;
|
|
35
|
-
signAllTransactions<T extends Transaction | VersionedTransaction>(
|
|
35
|
+
signAllTransactions<T extends Transaction | VersionedTransaction>(transactions: T[]): Promise<T[]>;
|
|
36
36
|
signAndSendTransaction<T extends Transaction | VersionedTransaction>(transaction: T, options?: SendOptions): Promise<{
|
|
37
37
|
signature: TransactionSignature;
|
|
38
38
|
}>;
|
|
@@ -23,11 +23,9 @@ class TurnkeySolanaSigner {
|
|
|
23
23
|
return this.walletConnector.signTransaction(transaction);
|
|
24
24
|
});
|
|
25
25
|
}
|
|
26
|
-
signAllTransactions(
|
|
27
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
28
|
-
_transactions) {
|
|
26
|
+
signAllTransactions(transactions) {
|
|
29
27
|
return __awaiter(this, void 0, void 0, function* () {
|
|
30
|
-
|
|
28
|
+
return this.walletConnector.signAllTransactions(transactions);
|
|
31
29
|
});
|
|
32
30
|
}
|
|
33
31
|
signAndSendTransaction(transaction, options) {
|
|
@@ -6,7 +6,6 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
6
6
|
var _tslib = require('../../../_virtual/_tslib.cjs');
|
|
7
7
|
var web3_js = require('@solana/web3.js');
|
|
8
8
|
var webauthnStamper = require('@turnkey/webauthn-stamper');
|
|
9
|
-
var http = require('@turnkey/http');
|
|
10
9
|
var solana = require('@turnkey/solana');
|
|
11
10
|
var iframeStamper = require('@turnkey/iframe-stamper');
|
|
12
11
|
var walletConnectorCore = require('@dynamic-labs/wallet-connector-core');
|
|
@@ -14,7 +13,6 @@ var utils = require('@dynamic-labs/utils');
|
|
|
14
13
|
var solanaCore = require('@dynamic-labs/solana-core');
|
|
15
14
|
var embeddedWallet = require('@dynamic-labs/embedded-wallet');
|
|
16
15
|
var createSolanaConnection = require('../utils/createSolanaConnection/createSolanaConnection.cjs');
|
|
17
|
-
var transactionDecoder = require('../utils/transactionDecoder/transactionDecoder.cjs');
|
|
18
16
|
var api = require('../utils/api/api.cjs');
|
|
19
17
|
var TurnkeySolanaSigner = require('./TurnkeySolanaSigner.cjs');
|
|
20
18
|
|
|
@@ -44,17 +42,13 @@ class TurnkeySolanaWalletConnector extends embeddedWallet.TurnkeyWalletConnector
|
|
|
44
42
|
}
|
|
45
43
|
throw new Error('Failed to get environment id');
|
|
46
44
|
};
|
|
47
|
-
this.stampCreateWalletAccountRequest = (_b) => _tslib.__awaiter(this, [_b], void 0, function* ({ request, }) {
|
|
48
|
-
yield this.createOrRestoreSession();
|
|
49
|
-
const turnkeyClient = this.getTurnkeyClient();
|
|
50
|
-
return turnkeyClient.stampCreateWalletAccounts(request);
|
|
51
|
-
});
|
|
52
45
|
this.solNetworks = props.solNetworks;
|
|
53
46
|
this.walletUiUtils = props.walletUiUtils;
|
|
54
47
|
this._turnkeyAccount = undefined;
|
|
55
48
|
this._connectionClient = undefined;
|
|
49
|
+
this.connectionConfig = props.connectionConfig;
|
|
56
50
|
this.chainRpcProviders = props.chainRpcProviders;
|
|
57
|
-
(_a = this.chainRpcProviders) === null || _a === void 0 ? void 0 : _a.registerSolanaProviders();
|
|
51
|
+
(_a = this.chainRpcProviders) === null || _a === void 0 ? void 0 : _a.registerSolanaProviders(this.connectionConfig);
|
|
58
52
|
this.__turnkeyClient = this.getTurnkeyClient();
|
|
59
53
|
}
|
|
60
54
|
getRpcUrl() {
|
|
@@ -70,7 +64,9 @@ class TurnkeySolanaWalletConnector extends embeddedWallet.TurnkeyWalletConnector
|
|
|
70
64
|
const rpcUrl = this.getRpcUrl();
|
|
71
65
|
if (!rpcUrl)
|
|
72
66
|
throw new utils.DynamicError('No rpcUrl');
|
|
73
|
-
|
|
67
|
+
const config = typeof commitmentOrConfig === 'string'
|
|
68
|
+
? Object.assign(Object.assign({}, this.connectionConfig), { commitment: commitmentOrConfig }) : Object.assign(Object.assign({}, this.connectionConfig), commitmentOrConfig);
|
|
69
|
+
this._connectionClient = createSolanaConnection.createSolanaConnection(rpcUrl, config);
|
|
74
70
|
}
|
|
75
71
|
return this._connectionClient;
|
|
76
72
|
}
|
|
@@ -159,23 +155,6 @@ class TurnkeySolanaWalletConnector extends embeddedWallet.TurnkeyWalletConnector
|
|
|
159
155
|
return this.getTurnkeyAccount();
|
|
160
156
|
});
|
|
161
157
|
}
|
|
162
|
-
getTurnkeyClient() {
|
|
163
|
-
var _a;
|
|
164
|
-
let rpId = utils.getTLD();
|
|
165
|
-
if (!rpId) {
|
|
166
|
-
rpId = utils.PlatformService.getHostname();
|
|
167
|
-
}
|
|
168
|
-
const passkeyStamper = embeddedWallet.PasskeyService.createWebauthnStamper({
|
|
169
|
-
rpId,
|
|
170
|
-
});
|
|
171
|
-
const apiKeyStamper = embeddedWallet.TurnkeyWalletConnectorBase === null || embeddedWallet.TurnkeyWalletConnectorBase === void 0 ? void 0 : embeddedWallet.TurnkeyWalletConnectorBase.apiKeyStamper;
|
|
172
|
-
const stamper = apiKeyStamper !== null && apiKeyStamper !== void 0 ? apiKeyStamper : passkeyStamper;
|
|
173
|
-
this.__turnkeyClient =
|
|
174
|
-
(_a = this.getAuthenticatorHandler().client) !== null && _a !== void 0 ? _a : new http.TurnkeyClient({
|
|
175
|
-
baseUrl: embeddedWallet.TURNKEY_API_BASE_URL,
|
|
176
|
-
}, stamper);
|
|
177
|
-
return this.__turnkeyClient;
|
|
178
|
-
}
|
|
179
158
|
createTurnkeyAccount(_a) {
|
|
180
159
|
return _tslib.__awaiter(this, arguments, void 0, function* ({ organizationId, }) {
|
|
181
160
|
const turnkeyClient = this.getTurnkeyClient();
|
|
@@ -260,7 +239,7 @@ class TurnkeySolanaWalletConnector extends embeddedWallet.TurnkeyWalletConnector
|
|
|
260
239
|
return utils.bufferToBase64(signedRawMessage);
|
|
261
240
|
});
|
|
262
241
|
}
|
|
263
|
-
|
|
242
|
+
internalSignTransaction(transaction) {
|
|
264
243
|
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
265
244
|
yield this.createOrRestoreSession();
|
|
266
245
|
let account = yield this.getTurnkeyAccount();
|
|
@@ -288,27 +267,84 @@ class TurnkeySolanaWalletConnector extends embeddedWallet.TurnkeyWalletConnector
|
|
|
288
267
|
return transaction;
|
|
289
268
|
});
|
|
290
269
|
}
|
|
291
|
-
|
|
270
|
+
signTransaction(transaction) {
|
|
292
271
|
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
293
|
-
var _a;
|
|
294
272
|
if (!this.turnkeyAddress)
|
|
295
|
-
throw new utils.DynamicError('
|
|
296
|
-
const
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
transaction
|
|
300
|
-
|
|
273
|
+
throw new utils.DynamicError('No turnkey account');
|
|
274
|
+
const uiTransaction = new solanaCore.SolanaUiTransaction({
|
|
275
|
+
connection: this.getConnection('confirmed'),
|
|
276
|
+
from: this.turnkeyAddress,
|
|
277
|
+
multipleTransactions: [transaction],
|
|
278
|
+
onSubmit: () => _tslib.__awaiter(this, void 0, void 0, function* () { return this.internalSignTransaction(transaction); }),
|
|
279
|
+
});
|
|
280
|
+
return this.walletUiUtils.signTransaction(this, uiTransaction);
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
createUiTransaction(from) {
|
|
284
|
+
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
285
|
+
yield this.validateActiveWallet(from);
|
|
286
|
+
const transaction = new solanaCore.SolanaUiTransaction({
|
|
287
|
+
connection: this.getConnection('confirmed'),
|
|
288
|
+
from,
|
|
289
|
+
onSubmit: (transaction) => _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
290
|
+
if (!transaction)
|
|
291
|
+
return undefined;
|
|
292
|
+
return this.internalSignAndSendTransaction(transaction);
|
|
293
|
+
}),
|
|
294
|
+
});
|
|
295
|
+
return transaction;
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
internalSignAllTransactions(transactions) {
|
|
299
|
+
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
300
|
+
yield this.createOrRestoreSession();
|
|
301
|
+
let account = yield this.getTurnkeyAccount();
|
|
302
|
+
const address = this.turnkeyAddress;
|
|
303
|
+
if (!account || !address) {
|
|
304
|
+
throw new Error('No turnkey account');
|
|
301
305
|
}
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
+
try {
|
|
307
|
+
const signedTransactions = yield account.signAllTransactions(transactions, address);
|
|
308
|
+
return signedTransactions;
|
|
309
|
+
}
|
|
310
|
+
catch (err) {
|
|
311
|
+
if (embeddedWallet.TURNKEY_SDK_SESSION_KEY_RETRYABLE_ERRORS.some((errorMsg) => err.message.includes(errorMsg))) {
|
|
312
|
+
yield this.removeSessionKeys();
|
|
313
|
+
yield this.createOrRestoreSession({
|
|
314
|
+
ignoreRestore: true,
|
|
315
|
+
});
|
|
316
|
+
account = (yield this.getTurnkeyAccount());
|
|
317
|
+
const signedTransactions = yield account.signAllTransactions(transactions, address);
|
|
318
|
+
return signedTransactions;
|
|
319
|
+
}
|
|
320
|
+
else {
|
|
321
|
+
embeddedWallet.logger.error('[TK] failed to perform SignAllTransactions activity', err);
|
|
322
|
+
throw err;
|
|
323
|
+
}
|
|
306
324
|
}
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
signAllTransactions(transactions) {
|
|
328
|
+
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
329
|
+
if (!this.turnkeyAddress)
|
|
330
|
+
throw new utils.DynamicError('No turnkey account');
|
|
331
|
+
const uiTransaction = new solanaCore.SolanaUiTransaction({
|
|
332
|
+
connection: this.getConnection('confirmed'),
|
|
333
|
+
from: this.turnkeyAddress,
|
|
334
|
+
multipleTransactions: transactions,
|
|
335
|
+
onSubmit: () => _tslib.__awaiter(this, void 0, void 0, function* () { return this.internalSignAllTransactions(transactions); }),
|
|
336
|
+
});
|
|
337
|
+
return this.walletUiUtils.signTransaction(this, uiTransaction);
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
internalSignAndSendTransaction(transaction, options) {
|
|
341
|
+
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
342
|
+
var _a, _b;
|
|
343
|
+
if (!this.turnkeyAddress)
|
|
344
|
+
throw new utils.DynamicError('Solana wallet not found');
|
|
345
|
+
const currentConnection = this.getConnection((_b = (_a = this.connectionConfig) === null || _a === void 0 ? void 0 : _a.commitment) !== null && _b !== void 0 ? _b : 'confirmed');
|
|
346
|
+
const signedTransaction = yield this.internalSignTransaction(transaction);
|
|
347
|
+
const signature = yield currentConnection.sendRawTransaction(signedTransaction.serialize(), options);
|
|
312
348
|
// listen for tx confirmation until 60 seconds, which is ~150 blocks expiration
|
|
313
349
|
return new Promise((resolve, reject) => {
|
|
314
350
|
const timeout = setTimeout(() => {
|
|
@@ -328,44 +364,15 @@ class TurnkeySolanaWalletConnector extends embeddedWallet.TurnkeyWalletConnector
|
|
|
328
364
|
}
|
|
329
365
|
signAndSendTransaction(transaction, options) {
|
|
330
366
|
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
331
|
-
var _a;
|
|
332
367
|
if (!this.turnkeyAddress)
|
|
333
368
|
throw new utils.DynamicError('Solana wallet not found');
|
|
334
|
-
|
|
335
|
-
try {
|
|
336
|
-
if ((yield this.getNetwork()) === 'mainnet') {
|
|
337
|
-
optimizedTransaction = (yield api.optimizeSolanaTransaction(this.getEnvId(), transaction, (_a = this.turnkeyAddress) !== null && _a !== void 0 ? _a : ''));
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
catch (e) {
|
|
341
|
-
embeddedWallet.logger.warn('Failed to optimize transaction', e);
|
|
342
|
-
}
|
|
343
|
-
const transactionsData = yield transactionDecoder.decodeTransaction(optimizedTransaction, this.getConnection(), this.turnkeyAddress);
|
|
344
|
-
if (!(transactionsData === null || transactionsData === void 0 ? void 0 : transactionsData.length)) {
|
|
345
|
-
throw new utils.DynamicError('Incorrectly formatted transaction instructions');
|
|
346
|
-
}
|
|
347
|
-
let spent;
|
|
348
|
-
let insufficientFunds = false;
|
|
349
|
-
try {
|
|
350
|
-
spent = yield transactionDecoder.getTotalSolanaSpend(optimizedTransaction, this.getConnection(), this.turnkeyAddress);
|
|
351
|
-
}
|
|
352
|
-
catch (e) {
|
|
353
|
-
if (e.message === 'Insufficient funds') {
|
|
354
|
-
insufficientFunds = true;
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
const to = transactionDecoder.summarizeTransactionDecodedData(transactionsData);
|
|
369
|
+
const optimizedTransaction = yield this.optimizeTransaction(transaction);
|
|
358
370
|
const uiTransaction = new solanaCore.SolanaUiTransaction({
|
|
359
|
-
connection: this.getConnection(),
|
|
371
|
+
connection: this.getConnection('confirmed'),
|
|
360
372
|
from: this.turnkeyAddress,
|
|
373
|
+
multipleTransactions: [optimizedTransaction],
|
|
361
374
|
onSubmit: () => _tslib.__awaiter(this, void 0, void 0, function* () { return this.internalSignAndSendTransaction(optimizedTransaction, options); }),
|
|
362
|
-
originalTransaction: optimizedTransaction,
|
|
363
375
|
});
|
|
364
|
-
uiTransaction.to = to;
|
|
365
|
-
uiTransaction.value = spent;
|
|
366
|
-
if (insufficientFunds) {
|
|
367
|
-
uiTransaction.notEnoughFundsError = true;
|
|
368
|
-
}
|
|
369
376
|
// TODO: remove this. We should not be passing references to wallet connectors
|
|
370
377
|
return this.walletUiUtils.sendTransaction(this, uiTransaction);
|
|
371
378
|
});
|
|
@@ -408,16 +415,21 @@ class TurnkeySolanaWalletConnector extends embeddedWallet.TurnkeyWalletConnector
|
|
|
408
415
|
lamportsToSol(lamports) {
|
|
409
416
|
return lamports / web3_js.LAMPORTS_PER_SOL;
|
|
410
417
|
}
|
|
411
|
-
|
|
418
|
+
optimizeTransaction(transaction) {
|
|
412
419
|
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
420
|
+
var _a;
|
|
421
|
+
let optimizedTransaction = transaction;
|
|
422
|
+
try {
|
|
423
|
+
// we cannot optimize partially signed transactions as once a tx is modified the signatures are no longer valid
|
|
424
|
+
if ((yield this.getNetwork()) === 'mainnet' &&
|
|
425
|
+
!solanaCore.isTxAlreadySigned(transaction)) {
|
|
426
|
+
optimizedTransaction = (yield api.optimizeSolanaTransaction(this.getEnvId(), transaction, (_a = this.turnkeyAddress) !== null && _a !== void 0 ? _a : ''));
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
catch (e) {
|
|
430
|
+
embeddedWallet.logger.warn('Failed to optimize transaction', e);
|
|
431
|
+
}
|
|
432
|
+
return optimizedTransaction;
|
|
421
433
|
});
|
|
422
434
|
}
|
|
423
435
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Commitment, Connection, ConnectionConfig, Transaction, VersionedTransaction, ConfirmOptions, Signer, SendOptions } from '@solana/web3.js';
|
|
2
|
-
import { TurnkeyApiTypes } from '@turnkey/http';
|
|
3
2
|
import { GenericNetwork, IUITransaction, WalletUiUtils } from '@dynamic-labs/types';
|
|
4
3
|
import { Chain, ISendBalanceWalletConnector, InternalWalletConnector } from '@dynamic-labs/wallet-connector-core';
|
|
5
4
|
import { WalletBookSchema } from '@dynamic-labs/wallet-book';
|
|
@@ -16,6 +15,7 @@ export type TurnkeySolanaConnectorProps = {
|
|
|
16
15
|
solNetworks: GenericNetwork[];
|
|
17
16
|
appName?: string;
|
|
18
17
|
chainRpcProviders: IChainRpcProviders;
|
|
18
|
+
connectionConfig?: ConnectionConfig;
|
|
19
19
|
};
|
|
20
20
|
export declare class TurnkeySolanaWalletConnector extends TurnkeyWalletConnectorBase implements ISendBalanceWalletConnector {
|
|
21
21
|
ChainWallet: typeof SolanaWallet;
|
|
@@ -26,7 +26,7 @@ export declare class TurnkeySolanaWalletConnector extends TurnkeyWalletConnector
|
|
|
26
26
|
private walletUiUtils;
|
|
27
27
|
private _turnkeyAccount;
|
|
28
28
|
private _connectionClient;
|
|
29
|
-
private
|
|
29
|
+
private connectionConfig;
|
|
30
30
|
constructor(nameAndKey: TurnkeyWalletConnectorNameAndKey, props: TurnkeySolanaConnectorProps);
|
|
31
31
|
getRpcUrl(): string;
|
|
32
32
|
getConnection(commitmentOrConfig?: Commitment | ConnectionConfig): Connection;
|
|
@@ -39,7 +39,6 @@ export declare class TurnkeySolanaWalletConnector extends TurnkeyWalletConnector
|
|
|
39
39
|
getAccount(): string | undefined;
|
|
40
40
|
endSession(): Promise<void>;
|
|
41
41
|
private refreshTurnkeyAccount;
|
|
42
|
-
private getTurnkeyClient;
|
|
43
42
|
private createTurnkeyAccount;
|
|
44
43
|
private getTurnkeyAccount;
|
|
45
44
|
getSigner(): Promise<TurnkeySolanaSigner | undefined>;
|
|
@@ -47,14 +46,15 @@ export declare class TurnkeySolanaWalletConnector extends TurnkeyWalletConnector
|
|
|
47
46
|
signUint8ArrayMessage(encodedMessage: Uint8Array): Promise<Uint8Array>;
|
|
48
47
|
getEnvId: () => any;
|
|
49
48
|
signMessage(messageToSign: string): Promise<string | undefined>;
|
|
49
|
+
internalSignTransaction<T extends Transaction | VersionedTransaction>(transaction: T): Promise<T>;
|
|
50
50
|
signTransaction<T extends Transaction | VersionedTransaction>(transaction: T): Promise<T>;
|
|
51
|
+
createUiTransaction(from: string): Promise<IUITransaction>;
|
|
52
|
+
internalSignAllTransactions<T extends Transaction | VersionedTransaction>(transactions: T[]): Promise<T[]>;
|
|
53
|
+
signAllTransactions<T extends Transaction | VersionedTransaction>(transactions: T[]): Promise<T[]>;
|
|
51
54
|
internalSignAndSendTransaction<T extends Transaction | VersionedTransaction>(transaction: T, options?: SendOptions): Promise<string>;
|
|
52
55
|
signAndSendTransaction<T extends Transaction | VersionedTransaction>(transaction: T, options?: SendOptions): Promise<string>;
|
|
53
56
|
sendTransaction<T extends Transaction | VersionedTransaction>(transaction: T, connection: Connection, options?: SendTransactionOptions): Promise<string>;
|
|
54
57
|
private lamportsToSol;
|
|
55
|
-
|
|
56
|
-
stampCreateWalletAccountRequest: ({ request, }: {
|
|
57
|
-
request: TurnkeyApiTypes['v1CreateWalletAccountsRequest'];
|
|
58
|
-
}) => Promise<import("@turnkey/http").TSignedRequest>;
|
|
58
|
+
private optimizeTransaction;
|
|
59
59
|
}
|
|
60
60
|
export {};
|
|
@@ -2,15 +2,13 @@
|
|
|
2
2
|
import { __awaiter, __rest } from '../../../_virtual/_tslib.js';
|
|
3
3
|
import { LAMPORTS_PER_SOL, PublicKey } from '@solana/web3.js';
|
|
4
4
|
import { WebauthnStamper } from '@turnkey/webauthn-stamper';
|
|
5
|
-
import { TurnkeyClient } from '@turnkey/http';
|
|
6
5
|
import { TurnkeySigner } from '@turnkey/solana';
|
|
7
6
|
import { IframeStamper } from '@turnkey/iframe-stamper';
|
|
8
7
|
import { isSameAddress } from '@dynamic-labs/wallet-connector-core';
|
|
9
|
-
import { DynamicError,
|
|
10
|
-
import { SolanaWallet, ProviderChain, getGenesisHashLSKey, SolanaUiTransaction } from '@dynamic-labs/solana-core';
|
|
11
|
-
import { TurnkeyWalletConnectorBase, findTurnkeyVerifiedCredentials,
|
|
8
|
+
import { DynamicError, bufferToBase64 } from '@dynamic-labs/utils';
|
|
9
|
+
import { SolanaWallet, ProviderChain, getGenesisHashLSKey, SolanaUiTransaction, isTxAlreadySigned } from '@dynamic-labs/solana-core';
|
|
10
|
+
import { TurnkeyWalletConnectorBase, findTurnkeyVerifiedCredentials, TURNKEY_SDK_SESSION_KEY_RETRYABLE_ERRORS, logger } from '@dynamic-labs/embedded-wallet';
|
|
12
11
|
import { createSolanaConnection } from '../utils/createSolanaConnection/createSolanaConnection.js';
|
|
13
|
-
import { decodeTransaction, getTotalSolanaSpend, summarizeTransactionDecodedData } from '../utils/transactionDecoder/transactionDecoder.js';
|
|
14
12
|
import { optimizeSolanaTransaction } from '../utils/api/api.js';
|
|
15
13
|
import { TurnkeySolanaSigner } from './TurnkeySolanaSigner.js';
|
|
16
14
|
|
|
@@ -40,17 +38,13 @@ class TurnkeySolanaWalletConnector extends TurnkeyWalletConnectorBase {
|
|
|
40
38
|
}
|
|
41
39
|
throw new Error('Failed to get environment id');
|
|
42
40
|
};
|
|
43
|
-
this.stampCreateWalletAccountRequest = (_b) => __awaiter(this, [_b], void 0, function* ({ request, }) {
|
|
44
|
-
yield this.createOrRestoreSession();
|
|
45
|
-
const turnkeyClient = this.getTurnkeyClient();
|
|
46
|
-
return turnkeyClient.stampCreateWalletAccounts(request);
|
|
47
|
-
});
|
|
48
41
|
this.solNetworks = props.solNetworks;
|
|
49
42
|
this.walletUiUtils = props.walletUiUtils;
|
|
50
43
|
this._turnkeyAccount = undefined;
|
|
51
44
|
this._connectionClient = undefined;
|
|
45
|
+
this.connectionConfig = props.connectionConfig;
|
|
52
46
|
this.chainRpcProviders = props.chainRpcProviders;
|
|
53
|
-
(_a = this.chainRpcProviders) === null || _a === void 0 ? void 0 : _a.registerSolanaProviders();
|
|
47
|
+
(_a = this.chainRpcProviders) === null || _a === void 0 ? void 0 : _a.registerSolanaProviders(this.connectionConfig);
|
|
54
48
|
this.__turnkeyClient = this.getTurnkeyClient();
|
|
55
49
|
}
|
|
56
50
|
getRpcUrl() {
|
|
@@ -66,7 +60,9 @@ class TurnkeySolanaWalletConnector extends TurnkeyWalletConnectorBase {
|
|
|
66
60
|
const rpcUrl = this.getRpcUrl();
|
|
67
61
|
if (!rpcUrl)
|
|
68
62
|
throw new DynamicError('No rpcUrl');
|
|
69
|
-
|
|
63
|
+
const config = typeof commitmentOrConfig === 'string'
|
|
64
|
+
? Object.assign(Object.assign({}, this.connectionConfig), { commitment: commitmentOrConfig }) : Object.assign(Object.assign({}, this.connectionConfig), commitmentOrConfig);
|
|
65
|
+
this._connectionClient = createSolanaConnection(rpcUrl, config);
|
|
70
66
|
}
|
|
71
67
|
return this._connectionClient;
|
|
72
68
|
}
|
|
@@ -155,23 +151,6 @@ class TurnkeySolanaWalletConnector extends TurnkeyWalletConnectorBase {
|
|
|
155
151
|
return this.getTurnkeyAccount();
|
|
156
152
|
});
|
|
157
153
|
}
|
|
158
|
-
getTurnkeyClient() {
|
|
159
|
-
var _a;
|
|
160
|
-
let rpId = getTLD();
|
|
161
|
-
if (!rpId) {
|
|
162
|
-
rpId = PlatformService.getHostname();
|
|
163
|
-
}
|
|
164
|
-
const passkeyStamper = PasskeyService.createWebauthnStamper({
|
|
165
|
-
rpId,
|
|
166
|
-
});
|
|
167
|
-
const apiKeyStamper = TurnkeyWalletConnectorBase === null || TurnkeyWalletConnectorBase === void 0 ? void 0 : TurnkeyWalletConnectorBase.apiKeyStamper;
|
|
168
|
-
const stamper = apiKeyStamper !== null && apiKeyStamper !== void 0 ? apiKeyStamper : passkeyStamper;
|
|
169
|
-
this.__turnkeyClient =
|
|
170
|
-
(_a = this.getAuthenticatorHandler().client) !== null && _a !== void 0 ? _a : new TurnkeyClient({
|
|
171
|
-
baseUrl: TURNKEY_API_BASE_URL,
|
|
172
|
-
}, stamper);
|
|
173
|
-
return this.__turnkeyClient;
|
|
174
|
-
}
|
|
175
154
|
createTurnkeyAccount(_a) {
|
|
176
155
|
return __awaiter(this, arguments, void 0, function* ({ organizationId, }) {
|
|
177
156
|
const turnkeyClient = this.getTurnkeyClient();
|
|
@@ -256,7 +235,7 @@ class TurnkeySolanaWalletConnector extends TurnkeyWalletConnectorBase {
|
|
|
256
235
|
return bufferToBase64(signedRawMessage);
|
|
257
236
|
});
|
|
258
237
|
}
|
|
259
|
-
|
|
238
|
+
internalSignTransaction(transaction) {
|
|
260
239
|
return __awaiter(this, void 0, void 0, function* () {
|
|
261
240
|
yield this.createOrRestoreSession();
|
|
262
241
|
let account = yield this.getTurnkeyAccount();
|
|
@@ -284,27 +263,84 @@ class TurnkeySolanaWalletConnector extends TurnkeyWalletConnectorBase {
|
|
|
284
263
|
return transaction;
|
|
285
264
|
});
|
|
286
265
|
}
|
|
287
|
-
|
|
266
|
+
signTransaction(transaction) {
|
|
288
267
|
return __awaiter(this, void 0, void 0, function* () {
|
|
289
|
-
var _a;
|
|
290
268
|
if (!this.turnkeyAddress)
|
|
291
|
-
throw new DynamicError('
|
|
292
|
-
const
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
transaction
|
|
296
|
-
|
|
269
|
+
throw new DynamicError('No turnkey account');
|
|
270
|
+
const uiTransaction = new SolanaUiTransaction({
|
|
271
|
+
connection: this.getConnection('confirmed'),
|
|
272
|
+
from: this.turnkeyAddress,
|
|
273
|
+
multipleTransactions: [transaction],
|
|
274
|
+
onSubmit: () => __awaiter(this, void 0, void 0, function* () { return this.internalSignTransaction(transaction); }),
|
|
275
|
+
});
|
|
276
|
+
return this.walletUiUtils.signTransaction(this, uiTransaction);
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
createUiTransaction(from) {
|
|
280
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
281
|
+
yield this.validateActiveWallet(from);
|
|
282
|
+
const transaction = new SolanaUiTransaction({
|
|
283
|
+
connection: this.getConnection('confirmed'),
|
|
284
|
+
from,
|
|
285
|
+
onSubmit: (transaction) => __awaiter(this, void 0, void 0, function* () {
|
|
286
|
+
if (!transaction)
|
|
287
|
+
return undefined;
|
|
288
|
+
return this.internalSignAndSendTransaction(transaction);
|
|
289
|
+
}),
|
|
290
|
+
});
|
|
291
|
+
return transaction;
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
internalSignAllTransactions(transactions) {
|
|
295
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
296
|
+
yield this.createOrRestoreSession();
|
|
297
|
+
let account = yield this.getTurnkeyAccount();
|
|
298
|
+
const address = this.turnkeyAddress;
|
|
299
|
+
if (!account || !address) {
|
|
300
|
+
throw new Error('No turnkey account');
|
|
297
301
|
}
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
+
try {
|
|
303
|
+
const signedTransactions = yield account.signAllTransactions(transactions, address);
|
|
304
|
+
return signedTransactions;
|
|
305
|
+
}
|
|
306
|
+
catch (err) {
|
|
307
|
+
if (TURNKEY_SDK_SESSION_KEY_RETRYABLE_ERRORS.some((errorMsg) => err.message.includes(errorMsg))) {
|
|
308
|
+
yield this.removeSessionKeys();
|
|
309
|
+
yield this.createOrRestoreSession({
|
|
310
|
+
ignoreRestore: true,
|
|
311
|
+
});
|
|
312
|
+
account = (yield this.getTurnkeyAccount());
|
|
313
|
+
const signedTransactions = yield account.signAllTransactions(transactions, address);
|
|
314
|
+
return signedTransactions;
|
|
315
|
+
}
|
|
316
|
+
else {
|
|
317
|
+
logger.error('[TK] failed to perform SignAllTransactions activity', err);
|
|
318
|
+
throw err;
|
|
319
|
+
}
|
|
302
320
|
}
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
signAllTransactions(transactions) {
|
|
324
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
325
|
+
if (!this.turnkeyAddress)
|
|
326
|
+
throw new DynamicError('No turnkey account');
|
|
327
|
+
const uiTransaction = new SolanaUiTransaction({
|
|
328
|
+
connection: this.getConnection('confirmed'),
|
|
329
|
+
from: this.turnkeyAddress,
|
|
330
|
+
multipleTransactions: transactions,
|
|
331
|
+
onSubmit: () => __awaiter(this, void 0, void 0, function* () { return this.internalSignAllTransactions(transactions); }),
|
|
332
|
+
});
|
|
333
|
+
return this.walletUiUtils.signTransaction(this, uiTransaction);
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
internalSignAndSendTransaction(transaction, options) {
|
|
337
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
338
|
+
var _a, _b;
|
|
339
|
+
if (!this.turnkeyAddress)
|
|
340
|
+
throw new DynamicError('Solana wallet not found');
|
|
341
|
+
const currentConnection = this.getConnection((_b = (_a = this.connectionConfig) === null || _a === void 0 ? void 0 : _a.commitment) !== null && _b !== void 0 ? _b : 'confirmed');
|
|
342
|
+
const signedTransaction = yield this.internalSignTransaction(transaction);
|
|
343
|
+
const signature = yield currentConnection.sendRawTransaction(signedTransaction.serialize(), options);
|
|
308
344
|
// listen for tx confirmation until 60 seconds, which is ~150 blocks expiration
|
|
309
345
|
return new Promise((resolve, reject) => {
|
|
310
346
|
const timeout = setTimeout(() => {
|
|
@@ -324,44 +360,15 @@ class TurnkeySolanaWalletConnector extends TurnkeyWalletConnectorBase {
|
|
|
324
360
|
}
|
|
325
361
|
signAndSendTransaction(transaction, options) {
|
|
326
362
|
return __awaiter(this, void 0, void 0, function* () {
|
|
327
|
-
var _a;
|
|
328
363
|
if (!this.turnkeyAddress)
|
|
329
364
|
throw new DynamicError('Solana wallet not found');
|
|
330
|
-
|
|
331
|
-
try {
|
|
332
|
-
if ((yield this.getNetwork()) === 'mainnet') {
|
|
333
|
-
optimizedTransaction = (yield optimizeSolanaTransaction(this.getEnvId(), transaction, (_a = this.turnkeyAddress) !== null && _a !== void 0 ? _a : ''));
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
catch (e) {
|
|
337
|
-
logger.warn('Failed to optimize transaction', e);
|
|
338
|
-
}
|
|
339
|
-
const transactionsData = yield decodeTransaction(optimizedTransaction, this.getConnection(), this.turnkeyAddress);
|
|
340
|
-
if (!(transactionsData === null || transactionsData === void 0 ? void 0 : transactionsData.length)) {
|
|
341
|
-
throw new DynamicError('Incorrectly formatted transaction instructions');
|
|
342
|
-
}
|
|
343
|
-
let spent;
|
|
344
|
-
let insufficientFunds = false;
|
|
345
|
-
try {
|
|
346
|
-
spent = yield getTotalSolanaSpend(optimizedTransaction, this.getConnection(), this.turnkeyAddress);
|
|
347
|
-
}
|
|
348
|
-
catch (e) {
|
|
349
|
-
if (e.message === 'Insufficient funds') {
|
|
350
|
-
insufficientFunds = true;
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
const to = summarizeTransactionDecodedData(transactionsData);
|
|
365
|
+
const optimizedTransaction = yield this.optimizeTransaction(transaction);
|
|
354
366
|
const uiTransaction = new SolanaUiTransaction({
|
|
355
|
-
connection: this.getConnection(),
|
|
367
|
+
connection: this.getConnection('confirmed'),
|
|
356
368
|
from: this.turnkeyAddress,
|
|
369
|
+
multipleTransactions: [optimizedTransaction],
|
|
357
370
|
onSubmit: () => __awaiter(this, void 0, void 0, function* () { return this.internalSignAndSendTransaction(optimizedTransaction, options); }),
|
|
358
|
-
originalTransaction: optimizedTransaction,
|
|
359
371
|
});
|
|
360
|
-
uiTransaction.to = to;
|
|
361
|
-
uiTransaction.value = spent;
|
|
362
|
-
if (insufficientFunds) {
|
|
363
|
-
uiTransaction.notEnoughFundsError = true;
|
|
364
|
-
}
|
|
365
372
|
// TODO: remove this. We should not be passing references to wallet connectors
|
|
366
373
|
return this.walletUiUtils.sendTransaction(this, uiTransaction);
|
|
367
374
|
});
|
|
@@ -404,16 +411,21 @@ class TurnkeySolanaWalletConnector extends TurnkeyWalletConnectorBase {
|
|
|
404
411
|
lamportsToSol(lamports) {
|
|
405
412
|
return lamports / LAMPORTS_PER_SOL;
|
|
406
413
|
}
|
|
407
|
-
|
|
414
|
+
optimizeTransaction(transaction) {
|
|
408
415
|
return __awaiter(this, void 0, void 0, function* () {
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
416
|
+
var _a;
|
|
417
|
+
let optimizedTransaction = transaction;
|
|
418
|
+
try {
|
|
419
|
+
// we cannot optimize partially signed transactions as once a tx is modified the signatures are no longer valid
|
|
420
|
+
if ((yield this.getNetwork()) === 'mainnet' &&
|
|
421
|
+
!isTxAlreadySigned(transaction)) {
|
|
422
|
+
optimizedTransaction = (yield optimizeSolanaTransaction(this.getEnvId(), transaction, (_a = this.turnkeyAddress) !== null && _a !== void 0 ? _a : ''));
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
catch (e) {
|
|
426
|
+
logger.warn('Failed to optimize transaction', e);
|
|
427
|
+
}
|
|
428
|
+
return optimizedTransaction;
|
|
417
429
|
});
|
|
418
430
|
}
|
|
419
431
|
}
|
package/src/lib/utils/index.d.ts
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { decodeTransaction, summarizeTransactionDecodedData, getTotalSolanaSpend, } from './transactionDecoder';
|