@dynamic-labs/embedded-wallet-solana 4.0.0-alpha.9 → 4.0.0
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 +483 -1
- package/package.cjs +6 -8
- package/package.js +6 -8
- package/package.json +14 -16
- package/src/TurnkeySolanaWalletConnectors.cjs +5 -1
- package/src/TurnkeySolanaWalletConnectors.js +5 -1
- 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 +96 -78
- package/src/lib/TurnkeySolanaWalletConnector/TurnkeySolanaWalletConnector.d.ts +7 -7
- package/src/lib/TurnkeySolanaWalletConnector/TurnkeySolanaWalletConnector.js +99 -81
- 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 -176
- package/src/lib/utils/transactionDecoder/transactionDecoder.d.ts +0 -12
- package/src/lib/utils/transactionDecoder/transactionDecoder.js +0 -170
|
@@ -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,12 +267,83 @@ class TurnkeySolanaWalletConnector extends embeddedWallet.TurnkeyWalletConnector
|
|
|
288
267
|
return transaction;
|
|
289
268
|
});
|
|
290
269
|
}
|
|
270
|
+
signTransaction(transaction) {
|
|
271
|
+
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
272
|
+
if (!this.turnkeyAddress)
|
|
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');
|
|
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
|
+
}
|
|
324
|
+
}
|
|
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
|
+
}
|
|
291
340
|
internalSignAndSendTransaction(transaction, options) {
|
|
292
341
|
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
342
|
+
var _a, _b;
|
|
293
343
|
if (!this.turnkeyAddress)
|
|
294
344
|
throw new utils.DynamicError('Solana wallet not found');
|
|
295
|
-
const currentConnection = this.getConnection('confirmed');
|
|
296
|
-
const signedTransaction = yield this.
|
|
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);
|
|
297
347
|
const signature = yield currentConnection.sendRawTransaction(signedTransaction.serialize(), options);
|
|
298
348
|
// listen for tx confirmation until 60 seconds, which is ~150 blocks expiration
|
|
299
349
|
return new Promise((resolve, reject) => {
|
|
@@ -314,52 +364,15 @@ class TurnkeySolanaWalletConnector extends embeddedWallet.TurnkeyWalletConnector
|
|
|
314
364
|
}
|
|
315
365
|
signAndSendTransaction(transaction, options) {
|
|
316
366
|
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
317
|
-
var _a;
|
|
318
367
|
if (!this.turnkeyAddress)
|
|
319
368
|
throw new utils.DynamicError('Solana wallet not found');
|
|
320
|
-
|
|
321
|
-
let alreadySigned = false;
|
|
322
|
-
if ('version' in transaction) {
|
|
323
|
-
alreadySigned = transaction.signatures.some((sig) => !sig.every((byte) => byte === 0));
|
|
324
|
-
}
|
|
325
|
-
else {
|
|
326
|
-
alreadySigned = transaction.signatures.some((sig) => sig.signature);
|
|
327
|
-
}
|
|
328
|
-
try {
|
|
329
|
-
// we cannot optimize partially signed transactions as once a tx is modified the signatures are no longer valid
|
|
330
|
-
if ((yield this.getNetwork()) === 'mainnet' && !alreadySigned) {
|
|
331
|
-
optimizedTransaction = (yield api.optimizeSolanaTransaction(this.getEnvId(), transaction, (_a = this.turnkeyAddress) !== null && _a !== void 0 ? _a : ''));
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
catch (e) {
|
|
335
|
-
embeddedWallet.logger.warn('Failed to optimize transaction', e);
|
|
336
|
-
}
|
|
337
|
-
const transactionsData = yield transactionDecoder.decodeTransaction(optimizedTransaction, this.getConnection(), this.turnkeyAddress);
|
|
338
|
-
if (!(transactionsData === null || transactionsData === void 0 ? void 0 : transactionsData.length)) {
|
|
339
|
-
throw new utils.DynamicError('Incorrectly formatted transaction instructions');
|
|
340
|
-
}
|
|
341
|
-
let spent;
|
|
342
|
-
let insufficientFunds = false;
|
|
343
|
-
try {
|
|
344
|
-
spent = yield transactionDecoder.getTotalSolanaSpend(optimizedTransaction, this.getConnection(), this.turnkeyAddress);
|
|
345
|
-
}
|
|
346
|
-
catch (e) {
|
|
347
|
-
if (e.message === 'Insufficient funds') {
|
|
348
|
-
insufficientFunds = true;
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
const to = transactionDecoder.summarizeTransactionDecodedData(transactionsData);
|
|
369
|
+
const optimizedTransaction = yield this.optimizeTransaction(transaction);
|
|
352
370
|
const uiTransaction = new solanaCore.SolanaUiTransaction({
|
|
353
|
-
connection: this.getConnection(),
|
|
371
|
+
connection: this.getConnection('confirmed'),
|
|
354
372
|
from: this.turnkeyAddress,
|
|
373
|
+
multipleTransactions: [optimizedTransaction],
|
|
355
374
|
onSubmit: () => _tslib.__awaiter(this, void 0, void 0, function* () { return this.internalSignAndSendTransaction(optimizedTransaction, options); }),
|
|
356
|
-
originalTransaction: optimizedTransaction,
|
|
357
375
|
});
|
|
358
|
-
uiTransaction.to = to;
|
|
359
|
-
uiTransaction.value = spent;
|
|
360
|
-
if (insufficientFunds) {
|
|
361
|
-
uiTransaction.notEnoughFundsError = true;
|
|
362
|
-
}
|
|
363
376
|
// TODO: remove this. We should not be passing references to wallet connectors
|
|
364
377
|
return this.walletUiUtils.sendTransaction(this, uiTransaction);
|
|
365
378
|
});
|
|
@@ -402,16 +415,21 @@ class TurnkeySolanaWalletConnector extends embeddedWallet.TurnkeyWalletConnector
|
|
|
402
415
|
lamportsToSol(lamports) {
|
|
403
416
|
return lamports / web3_js.LAMPORTS_PER_SOL;
|
|
404
417
|
}
|
|
405
|
-
|
|
418
|
+
optimizeTransaction(transaction) {
|
|
406
419
|
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
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;
|
|
415
433
|
});
|
|
416
434
|
}
|
|
417
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,12 +263,83 @@ class TurnkeySolanaWalletConnector extends TurnkeyWalletConnectorBase {
|
|
|
284
263
|
return transaction;
|
|
285
264
|
});
|
|
286
265
|
}
|
|
266
|
+
signTransaction(transaction) {
|
|
267
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
268
|
+
if (!this.turnkeyAddress)
|
|
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');
|
|
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
|
+
}
|
|
320
|
+
}
|
|
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
|
+
}
|
|
287
336
|
internalSignAndSendTransaction(transaction, options) {
|
|
288
337
|
return __awaiter(this, void 0, void 0, function* () {
|
|
338
|
+
var _a, _b;
|
|
289
339
|
if (!this.turnkeyAddress)
|
|
290
340
|
throw new DynamicError('Solana wallet not found');
|
|
291
|
-
const currentConnection = this.getConnection('confirmed');
|
|
292
|
-
const signedTransaction = yield this.
|
|
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);
|
|
293
343
|
const signature = yield currentConnection.sendRawTransaction(signedTransaction.serialize(), options);
|
|
294
344
|
// listen for tx confirmation until 60 seconds, which is ~150 blocks expiration
|
|
295
345
|
return new Promise((resolve, reject) => {
|
|
@@ -310,52 +360,15 @@ class TurnkeySolanaWalletConnector extends TurnkeyWalletConnectorBase {
|
|
|
310
360
|
}
|
|
311
361
|
signAndSendTransaction(transaction, options) {
|
|
312
362
|
return __awaiter(this, void 0, void 0, function* () {
|
|
313
|
-
var _a;
|
|
314
363
|
if (!this.turnkeyAddress)
|
|
315
364
|
throw new DynamicError('Solana wallet not found');
|
|
316
|
-
|
|
317
|
-
let alreadySigned = false;
|
|
318
|
-
if ('version' in transaction) {
|
|
319
|
-
alreadySigned = transaction.signatures.some((sig) => !sig.every((byte) => byte === 0));
|
|
320
|
-
}
|
|
321
|
-
else {
|
|
322
|
-
alreadySigned = transaction.signatures.some((sig) => sig.signature);
|
|
323
|
-
}
|
|
324
|
-
try {
|
|
325
|
-
// we cannot optimize partially signed transactions as once a tx is modified the signatures are no longer valid
|
|
326
|
-
if ((yield this.getNetwork()) === 'mainnet' && !alreadySigned) {
|
|
327
|
-
optimizedTransaction = (yield optimizeSolanaTransaction(this.getEnvId(), transaction, (_a = this.turnkeyAddress) !== null && _a !== void 0 ? _a : ''));
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
catch (e) {
|
|
331
|
-
logger.warn('Failed to optimize transaction', e);
|
|
332
|
-
}
|
|
333
|
-
const transactionsData = yield decodeTransaction(optimizedTransaction, this.getConnection(), this.turnkeyAddress);
|
|
334
|
-
if (!(transactionsData === null || transactionsData === void 0 ? void 0 : transactionsData.length)) {
|
|
335
|
-
throw new DynamicError('Incorrectly formatted transaction instructions');
|
|
336
|
-
}
|
|
337
|
-
let spent;
|
|
338
|
-
let insufficientFunds = false;
|
|
339
|
-
try {
|
|
340
|
-
spent = yield getTotalSolanaSpend(optimizedTransaction, this.getConnection(), this.turnkeyAddress);
|
|
341
|
-
}
|
|
342
|
-
catch (e) {
|
|
343
|
-
if (e.message === 'Insufficient funds') {
|
|
344
|
-
insufficientFunds = true;
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
const to = summarizeTransactionDecodedData(transactionsData);
|
|
365
|
+
const optimizedTransaction = yield this.optimizeTransaction(transaction);
|
|
348
366
|
const uiTransaction = new SolanaUiTransaction({
|
|
349
|
-
connection: this.getConnection(),
|
|
367
|
+
connection: this.getConnection('confirmed'),
|
|
350
368
|
from: this.turnkeyAddress,
|
|
369
|
+
multipleTransactions: [optimizedTransaction],
|
|
351
370
|
onSubmit: () => __awaiter(this, void 0, void 0, function* () { return this.internalSignAndSendTransaction(optimizedTransaction, options); }),
|
|
352
|
-
originalTransaction: optimizedTransaction,
|
|
353
371
|
});
|
|
354
|
-
uiTransaction.to = to;
|
|
355
|
-
uiTransaction.value = spent;
|
|
356
|
-
if (insufficientFunds) {
|
|
357
|
-
uiTransaction.notEnoughFundsError = true;
|
|
358
|
-
}
|
|
359
372
|
// TODO: remove this. We should not be passing references to wallet connectors
|
|
360
373
|
return this.walletUiUtils.sendTransaction(this, uiTransaction);
|
|
361
374
|
});
|
|
@@ -398,16 +411,21 @@ class TurnkeySolanaWalletConnector extends TurnkeyWalletConnectorBase {
|
|
|
398
411
|
lamportsToSol(lamports) {
|
|
399
412
|
return lamports / LAMPORTS_PER_SOL;
|
|
400
413
|
}
|
|
401
|
-
|
|
414
|
+
optimizeTransaction(transaction) {
|
|
402
415
|
return __awaiter(this, void 0, void 0, function* () {
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
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;
|
|
411
429
|
});
|
|
412
430
|
}
|
|
413
431
|
}
|
package/src/lib/utils/index.d.ts
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { decodeTransaction, summarizeTransactionDecodedData, getTotalSolanaSpend, } from './transactionDecoder';
|