@velocity-exchange/sdk 0.4.0 → 0.6.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/README.md +3 -3
- package/lib/browser/adminClient.d.ts +35 -0
- package/lib/browser/adminClient.js +65 -0
- package/lib/browser/config.js +6 -7
- package/lib/browser/constants/numericConstants.d.ts +1 -1
- package/lib/browser/constants/numericConstants.js +1 -1
- package/lib/browser/decode/user.js +5 -1
- package/lib/browser/idl/velocity.d.ts +146 -3
- package/lib/browser/idl/velocity.json +147 -4
- package/lib/browser/orderSubscriber/OrderSubscriber.js +3 -0
- package/lib/browser/pyth/pythLazerSubscriber.js +37 -27
- package/lib/browser/types.d.ts +4 -0
- package/lib/browser/user.d.ts +15 -0
- package/lib/browser/user.js +37 -1
- package/lib/browser/velocityClient.d.ts +46 -10
- package/lib/browser/velocityClient.js +107 -35
- package/lib/node/adminClient.d.ts +35 -0
- package/lib/node/adminClient.d.ts.map +1 -1
- package/lib/node/adminClient.js +65 -0
- package/lib/node/config.d.ts.map +1 -1
- package/lib/node/config.js +6 -7
- package/lib/node/constants/numericConstants.d.ts +1 -1
- package/lib/node/constants/numericConstants.d.ts.map +1 -1
- package/lib/node/constants/numericConstants.js +1 -1
- package/lib/node/decode/user.d.ts.map +1 -1
- package/lib/node/decode/user.js +5 -1
- package/lib/node/idl/velocity.d.ts +146 -3
- package/lib/node/idl/velocity.d.ts.map +1 -1
- package/lib/node/idl/velocity.json +147 -4
- package/lib/node/orderSubscriber/OrderSubscriber.d.ts.map +1 -1
- package/lib/node/orderSubscriber/OrderSubscriber.js +3 -0
- package/lib/node/pyth/pythLazerSubscriber.d.ts.map +1 -1
- package/lib/node/pyth/pythLazerSubscriber.js +37 -27
- package/lib/node/types.d.ts +4 -0
- package/lib/node/types.d.ts.map +1 -1
- package/lib/node/user.d.ts +15 -0
- package/lib/node/user.d.ts.map +1 -1
- package/lib/node/user.js +37 -1
- package/lib/node/velocityClient.d.ts +46 -10
- package/lib/node/velocityClient.d.ts.map +1 -1
- package/lib/node/velocityClient.js +107 -35
- package/package.json +7 -3
- package/.prettierignore +0 -1
- package/CHANGELOG.md +0 -132
- package/build-browser.js +0 -58
- package/bunfig.toml +0 -3
- package/esbuild-shims.js +0 -12
- package/scripts/deposit-isolated-positions.ts +0 -110
- package/scripts/find-flagged-users.ts +0 -213
- package/scripts/grpc-client-test-comparison.ts +0 -372
- package/scripts/grpc-multiuser-client-test-comparison.ts +0 -158
- package/scripts/postbuild.js +0 -95
- package/scripts/single-grpc-client-test.ts +0 -284
- package/scripts/withdraw-isolated-positions.ts +0 -174
- package/src/accounts/README_WebSocketAccountSubscriberV2.md +0 -95
- package/src/accounts/README_WebSocketProgramAccountSubscriberV2.md +0 -135
- package/src/accounts/basicUserAccountSubscriber.ts +0 -79
- package/src/accounts/basicUserStatsAccountSubscriber.ts +0 -87
- package/src/accounts/bulkAccountLoader.ts +0 -358
- package/src/accounts/bulkUserStatsSubscription.ts +0 -40
- package/src/accounts/bulkUserSubscription.ts +0 -39
- package/src/accounts/customizedCadenceBulkAccountLoader.ts +0 -250
- package/src/accounts/fetch.ts +0 -200
- package/src/accounts/grpcAccountSubscriber.ts +0 -225
- package/src/accounts/grpcInsuranceFundStakeAccountSubscriber.ts +0 -73
- package/src/accounts/grpcMultiAccountSubscriber.ts +0 -566
- package/src/accounts/grpcMultiUserAccountSubscriber.ts +0 -328
- package/src/accounts/grpcProgramAccountSubscriber.ts +0 -264
- package/src/accounts/grpcUserAccountSubscriber.ts +0 -63
- package/src/accounts/grpcUserStatsAccountSubscriber.ts +0 -65
- package/src/accounts/grpcVelocityClientAccountSubscriber.ts +0 -257
- package/src/accounts/grpcVelocityClientAccountSubscriberV2.ts +0 -941
- package/src/accounts/laserProgramAccountSubscriber.ts +0 -266
- package/src/accounts/oneShotUserAccountSubscriber.ts +0 -88
- package/src/accounts/oneShotUserStatsAccountSubscriber.ts +0 -94
- package/src/accounts/pollingInsuranceFundStakeAccountSubscriber.ts +0 -223
- package/src/accounts/pollingOracleAccountSubscriber.ts +0 -151
- package/src/accounts/pollingTokenAccountSubscriber.ts +0 -147
- package/src/accounts/pollingUserAccountSubscriber.ts +0 -198
- package/src/accounts/pollingUserStatsAccountSubscriber.ts +0 -180
- package/src/accounts/pollingVelocityClientAccountSubscriber.ts +0 -774
- package/src/accounts/testBulkAccountLoader.ts +0 -59
- package/src/accounts/types.ts +0 -428
- package/src/accounts/utils.ts +0 -90
- package/src/accounts/webSocketAccountSubscriber.ts +0 -304
- package/src/accounts/webSocketAccountSubscriberV2.ts +0 -536
- package/src/accounts/webSocketInsuranceFundStakeAccountSubscriber.ts +0 -171
- package/src/accounts/webSocketProgramAccountSubscriber.ts +0 -244
- package/src/accounts/webSocketProgramAccountSubscriberV2.ts +0 -1048
- package/src/accounts/webSocketProgramAccountsSubscriberV2.ts +0 -1042
- package/src/accounts/webSocketUserAccountSubscriber.ts +0 -139
- package/src/accounts/webSocketUserStatsAccountSubsriber.ts +0 -131
- package/src/accounts/webSocketVelocityClientAccountSubscriber.ts +0 -865
- package/src/accounts/webSocketVelocityClientAccountSubscriberV2.ts +0 -897
- package/src/accounts/websocketProgramUserAccountSubscriber.ts +0 -127
- package/src/addresses/marketAddresses.ts +0 -28
- package/src/addresses/pda.ts +0 -620
- package/src/adminClient.ts +0 -8136
- package/src/assert/assert.ts +0 -5
- package/src/auctionSubscriber/auctionSubscriber.ts +0 -86
- package/src/auctionSubscriber/auctionSubscriberGrpc.ts +0 -99
- package/src/auctionSubscriber/index.ts +0 -9
- package/src/auctionSubscriber/types.ts +0 -30
- package/src/bankrun/bankrunConnection.ts +0 -630
- package/src/blockhashSubscriber/BlockhashSubscriber.ts +0 -160
- package/src/blockhashSubscriber/index.ts +0 -6
- package/src/blockhashSubscriber/types.ts +0 -13
- package/src/clock/clockSubscriber.ts +0 -146
- package/src/config.ts +0 -312
- package/src/constants/index.ts +0 -9
- package/src/constants/numericConstants.ts +0 -194
- package/src/constants/perpMarkets.ts +0 -127
- package/src/constants/spotMarkets.ts +0 -104
- package/src/constants/txConstants.ts +0 -2
- package/src/constituentMap/constituentMap.ts +0 -305
- package/src/constituentMap/pollingConstituentAccountSubscriber.ts +0 -99
- package/src/constituentMap/webSocketConstituentAccountSubscriber.ts +0 -121
- package/src/core/VelocityCore.ts +0 -606
- package/src/core/index.ts +0 -12
- package/src/core/instructions/deposit.ts +0 -64
- package/src/core/instructions/fill.ts +0 -51
- package/src/core/instructions/funding.ts +0 -33
- package/src/core/instructions/liquidation.ts +0 -55
- package/src/core/instructions/orders.ts +0 -84
- package/src/core/instructions/perpOrders.ts +0 -312
- package/src/core/instructions/settlement.ts +0 -40
- package/src/core/instructions/trigger.ts +0 -41
- package/src/core/instructions/withdraw.ts +0 -65
- package/src/core/remainingAccounts.ts +0 -320
- package/src/core/signedMsg.ts +0 -109
- package/src/decode/customCoder.ts +0 -148
- package/src/decode/user.ts +0 -401
- package/src/dlob/DLOB.ts +0 -2793
- package/src/dlob/DLOBNode.ts +0 -305
- package/src/dlob/DLOBSubscriber.ts +0 -269
- package/src/dlob/NodeList.ts +0 -244
- package/src/dlob/orderBookLevels.ts +0 -695
- package/src/dlob/types.ts +0 -37
- package/src/events/eventList.ts +0 -114
- package/src/events/eventSubscriber.ts +0 -521
- package/src/events/eventsServerLogProvider.ts +0 -189
- package/src/events/fetchLogs.ts +0 -219
- package/src/events/parse.ts +0 -271
- package/src/events/pollingLogProvider.ts +0 -113
- package/src/events/sort.ts +0 -51
- package/src/events/txEventCache.ts +0 -92
- package/src/events/types.ts +0 -337
- package/src/events/webSocketLogProvider.ts +0 -152
- package/src/factory/bigNum.ts +0 -709
- package/src/factory/oracleClient.ts +0 -73
- package/src/idl/pyth.json +0 -142
- package/src/idl/pyth.ts +0 -97
- package/src/idl/pyth_solana_receiver.json +0 -628
- package/src/idl/token_faucet.json +0 -229
- package/src/idl/token_faucet.ts +0 -197
- package/src/idl/velocity.json +0 -23974
- package/src/idl/velocity.ts +0 -23980
- package/src/index.ts +0 -150
- package/src/indicative-quotes/indicativeQuotesSender.ts +0 -233
- package/src/isomorphic/README.md +0 -19
- package/src/isomorphic/anchor.browser.ts +0 -44
- package/src/isomorphic/anchor.node.ts +0 -1
- package/src/isomorphic/anchor.ts +0 -1
- package/src/isomorphic/anchor29.browser.ts +0 -24
- package/src/isomorphic/anchor29.node.ts +0 -1
- package/src/isomorphic/anchor29.ts +0 -1
- package/src/isomorphic/grpc.browser.ts +0 -4
- package/src/isomorphic/grpc.node.ts +0 -130
- package/src/isomorphic/grpc.ts +0 -1
- package/src/jupiter/jupiterClient.ts +0 -502
- package/src/keypair.ts +0 -32
- package/src/margin/README.md +0 -138
- package/src/marginCalculation.ts +0 -407
- package/src/marinade/idl/idl.json +0 -1962
- package/src/marinade/index.ts +0 -73
- package/src/marinade/types.ts +0 -3925
- package/src/math/amm.ts +0 -1758
- package/src/math/auction.ts +0 -480
- package/src/math/bankruptcy.ts +0 -138
- package/src/math/builder.ts +0 -130
- package/src/math/conversion.ts +0 -45
- package/src/math/exchangeStatus.ts +0 -261
- package/src/math/funding.ts +0 -498
- package/src/math/insurance.ts +0 -171
- package/src/math/liquidation.ts +0 -433
- package/src/math/margin.ts +0 -327
- package/src/math/market.ts +0 -487
- package/src/math/oracles.ts +0 -477
- package/src/math/orders.ts +0 -500
- package/src/math/position.ts +0 -381
- package/src/math/repeg.ts +0 -223
- package/src/math/spotBalance.ts +0 -996
- package/src/math/spotMarket.ts +0 -115
- package/src/math/spotPosition.ts +0 -263
- package/src/math/state.ts +0 -71
- package/src/math/superStake.ts +0 -602
- package/src/math/tiers.ts +0 -73
- package/src/math/trade.ts +0 -879
- package/src/math/utils.ts +0 -183
- package/src/memcmp.ts +0 -279
- package/src/oracles/oracleClientCache.ts +0 -41
- package/src/oracles/oracleId.ts +0 -99
- package/src/oracles/prelaunchOracleClient.ts +0 -63
- package/src/oracles/pythClient.ts +0 -125
- package/src/oracles/pythLazerClient.ts +0 -141
- package/src/oracles/quoteAssetOracleClient.ts +0 -43
- package/src/oracles/strictOraclePrice.ts +0 -40
- package/src/oracles/types.ts +0 -82
- package/src/oracles/utils.ts +0 -45
- package/src/orderParams.ts +0 -117
- package/src/orderSubscriber/OrderSubscriber.ts +0 -378
- package/src/orderSubscriber/PollingSubscription.ts +0 -50
- package/src/orderSubscriber/WebsocketSubscription.ts +0 -137
- package/src/orderSubscriber/grpcSubscription.ts +0 -155
- package/src/orderSubscriber/index.ts +0 -7
- package/src/orderSubscriber/types.ts +0 -64
- package/src/priorityFee/averageOverSlotsStrategy.ts +0 -17
- package/src/priorityFee/averageStrategy.ts +0 -13
- package/src/priorityFee/ewmaStrategy.ts +0 -51
- package/src/priorityFee/heliusPriorityFeeMethod.ts +0 -68
- package/src/priorityFee/index.ts +0 -16
- package/src/priorityFee/maxOverSlotsStrategy.ts +0 -18
- package/src/priorityFee/maxStrategy.ts +0 -8
- package/src/priorityFee/priorityFeeSubscriber.ts +0 -328
- package/src/priorityFee/priorityFeeSubscriberMap.ts +0 -134
- package/src/priorityFee/solanaPriorityFeeMethod.ts +0 -46
- package/src/priorityFee/types.ts +0 -82
- package/src/priorityFee/velocityPriorityFeeMethod.ts +0 -53
- package/src/pyth/constants.ts +0 -9
- package/src/pyth/index.ts +0 -15
- package/src/pyth/pythLazerSubscriber.ts +0 -365
- package/src/pyth/types.ts +0 -4451
- package/src/pyth/utils.ts +0 -13
- package/src/slot/SlotSubscriber.ts +0 -126
- package/src/slot/SlothashSubscriber.ts +0 -163
- package/src/swap/UnifiedSwapClient.ts +0 -315
- package/src/swift/grpcSignedMsgUserAccountSubscriber.ts +0 -81
- package/src/swift/index.ts +0 -10
- package/src/swift/signedMsgUserAccountSubscriber.ts +0 -251
- package/src/swift/swiftOrderSubscriber.ts +0 -351
- package/src/testClient.ts +0 -42
- package/src/titan/titanClient.ts +0 -438
- package/src/token/index.ts +0 -13
- package/src/tokenFaucet.ts +0 -296
- package/src/tx/baseTxSender.ts +0 -651
- package/src/tx/blockhashFetcher/baseBlockhashFetcher.ts +0 -31
- package/src/tx/blockhashFetcher/cachedBlockhashFetcher.ts +0 -105
- package/src/tx/blockhashFetcher/types.ts +0 -9
- package/src/tx/fastSingleTxSender.ts +0 -200
- package/src/tx/forwardOnlyTxSender.ts +0 -193
- package/src/tx/priorityFeeCalculator.ts +0 -117
- package/src/tx/reportTransactionError.ts +0 -176
- package/src/tx/retryTxSender.ts +0 -177
- package/src/tx/txHandler.ts +0 -1009
- package/src/tx/txParamProcessor.ts +0 -225
- package/src/tx/types.ts +0 -117
- package/src/tx/utils.ts +0 -133
- package/src/tx/whileValidTxSender.ts +0 -377
- package/src/types.ts +0 -2575
- package/src/user.ts +0 -5316
- package/src/userConfig.ts +0 -38
- package/src/userMap/PollingSubscription.ts +0 -61
- package/src/userMap/WebsocketSubscription.ts +0 -93
- package/src/userMap/grpcSubscription.ts +0 -93
- package/src/userMap/referrerMap.ts +0 -360
- package/src/userMap/revenueShareEscrowMap.ts +0 -342
- package/src/userMap/userMap.ts +0 -784
- package/src/userMap/userMapConfig.ts +0 -82
- package/src/userMap/userStatsMap.ts +0 -393
- package/src/userName.ts +0 -37
- package/src/userStats.ts +0 -159
- package/src/userStatsConfig.ts +0 -35
- package/src/util/TransactionConfirmationManager.ts +0 -333
- package/src/util/chainClock.ts +0 -65
- package/src/util/computeUnits.ts +0 -101
- package/src/util/digest.ts +0 -33
- package/src/util/ed25519Utils.ts +0 -95
- package/src/util/promiseTimeout.ts +0 -23
- package/src/velocityClient.ts +0 -14802
- package/src/velocityClientConfig.ts +0 -119
- package/src/wallet.ts +0 -91
- package/tests/VelocityCore/builder_escrow.test.ts +0 -121
- package/tests/VelocityCore/decode.test.ts +0 -16
- package/tests/VelocityCore/fill_trigger.test.ts +0 -73
- package/tests/VelocityCore/instructions.test.ts +0 -46
- package/tests/VelocityCore/pdas.test.ts +0 -30
- package/tests/VelocityCore/perp_orders.test.ts +0 -205
- package/tests/VelocityCore/remainingAccounts.test.ts +0 -72
- package/tests/VelocityCore/settlement_liquidation.test.ts +0 -69
- package/tests/accounts/customizedCadenceBulkAccountLoader.test.ts +0 -211
- package/tests/amm/test.ts +0 -2402
- package/tests/auctions/test.ts +0 -81
- package/tests/bn/test.ts +0 -355
- package/tests/builder/builderFee.test.ts +0 -42
- package/tests/ci/verifyConstants.ts +0 -393
- package/tests/decode/test.ts +0 -262
- package/tests/decode/userAccountBufferStrings.ts +0 -102
- package/tests/dlob/helpers.ts +0 -748
- package/tests/dlob/test.ts +0 -6969
- package/tests/dlob/tickSizeStandardization.ts +0 -545
- package/tests/events/parseLogsForCuUsage.ts +0 -139
- package/tests/exchangeStatus/test.ts +0 -45
- package/tests/insurance/test.ts +0 -40
- package/tests/liquidation/test.ts +0 -125
- package/tests/oracles/mmOracleGate.test.ts +0 -379
- package/tests/oracles/pythPegSnap.test.ts +0 -76
- package/tests/sdkParity/enumParity.test.ts +0 -84
- package/tests/sdkParity/marginCategoryFill.test.ts +0 -143
- package/tests/sdkParity/memcmpOffsets.test.ts +0 -139
- package/tests/spot/test.ts +0 -281
- package/tests/tx/TransactionConfirmationManager.test.ts +0 -312
- package/tests/tx/cachedBlockhashFetcher.test.ts +0 -96
- package/tests/tx/priorityFeeCalculator.ts +0 -77
- package/tests/tx/priorityFeeStrategy.ts +0 -95
- package/tests/user/bankruptcy.ts +0 -165
- package/tests/user/feeAndWithdrawLimits.ts +0 -284
- package/tests/user/getMarginCalculation.ts +0 -586
- package/tests/user/helpers.ts +0 -184
- package/tests/user/liquidations.ts +0 -129
- package/tests/user/marginCalculations.test.ts +0 -321
- package/tests/user/test.ts +0 -833
- package/tsconfig.browser.json +0 -18
- package/tsconfig.json +0 -36
package/src/tx/txHandler.ts
DELETED
|
@@ -1,1009 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Transaction building and sending infrastructure.
|
|
3
|
-
*
|
|
4
|
-
* `txHandler.ts` — base class for building versioned/legacy transactions with ALT support.
|
|
5
|
-
* `retryTxSender.ts` — retry loop with confirmation polling (default for most clients).
|
|
6
|
-
* `fastSingleTxSender.ts` — fire-and-forget path for latency-sensitive keeper bots.
|
|
7
|
-
* `priorityFeeCalculator.ts` — computes dynamic priority fees from recent fee estimates.
|
|
8
|
-
* `txParamProcessor.ts` — resolves CU limits and priority fees before send.
|
|
9
|
-
*
|
|
10
|
-
* Transaction sender is injected via VelocityClientConfig; swap implementations to tune
|
|
11
|
-
* confirmation strategy without changing instruction-building code.
|
|
12
|
-
*/
|
|
13
|
-
import {
|
|
14
|
-
AddressLookupTableAccount,
|
|
15
|
-
BlockhashWithExpiryBlockHeight,
|
|
16
|
-
Commitment,
|
|
17
|
-
ComputeBudgetProgram,
|
|
18
|
-
ConfirmOptions,
|
|
19
|
-
Connection,
|
|
20
|
-
Message,
|
|
21
|
-
MessageV0,
|
|
22
|
-
Signer,
|
|
23
|
-
SimulatedTransactionResponse,
|
|
24
|
-
Transaction,
|
|
25
|
-
TransactionInstruction,
|
|
26
|
-
TransactionMessage,
|
|
27
|
-
TransactionVersion,
|
|
28
|
-
VersionedTransaction,
|
|
29
|
-
} from '@solana/web3.js';
|
|
30
|
-
import { TransactionParamProcessor } from './txParamProcessor';
|
|
31
|
-
import bs58 from 'bs58';
|
|
32
|
-
import {
|
|
33
|
-
BaseTxParams,
|
|
34
|
-
VelocityClientMetricsEvents,
|
|
35
|
-
IWallet,
|
|
36
|
-
MappedRecord,
|
|
37
|
-
SignedTxData,
|
|
38
|
-
TxParams,
|
|
39
|
-
} from '../types';
|
|
40
|
-
import { containsComputeUnitIxs } from '../util/computeUnits';
|
|
41
|
-
import { CachedBlockhashFetcher } from './blockhashFetcher/cachedBlockhashFetcher';
|
|
42
|
-
import { BaseBlockhashFetcher } from './blockhashFetcher/baseBlockhashFetcher';
|
|
43
|
-
import { BlockhashFetcher } from './blockhashFetcher/types';
|
|
44
|
-
import {
|
|
45
|
-
getSizeOfTransaction,
|
|
46
|
-
isVersionedTransaction,
|
|
47
|
-
MAX_TX_BYTE_SIZE,
|
|
48
|
-
} from './utils';
|
|
49
|
-
import { DEFAULT_CONFIRMATION_OPTS } from '../config';
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Explanation for SIGNATURE_BLOCK_AND_EXPIRY:
|
|
53
|
-
*
|
|
54
|
-
* When the whileValidTxSender waits for confirmation of a given transaction, it needs the last available blockheight and blockhash used in the signature to do so. For pre-signed transactions, these values aren't attached to the transaction object by default. For a "scrappy" workaround which doesn't break backwards compatibility, the SIGNATURE_BLOCK_AND_EXPIRY property is simply attached to the transaction objects as they are created or signed in this handler despite a mismatch in the typescript types. If the values are attached to the transaction when they reach the whileValidTxSender, it can opt-in to use these values.
|
|
55
|
-
*/
|
|
56
|
-
|
|
57
|
-
const DEV_TRY_FORCE_TX_TIMEOUTS =
|
|
58
|
-
process.env.DEV_TRY_FORCE_TX_TIMEOUTS === 'true' || false;
|
|
59
|
-
|
|
60
|
-
export const COMPUTE_UNITS_DEFAULT = 200_000;
|
|
61
|
-
|
|
62
|
-
const BLOCKHASH_FETCH_RETRY_COUNT = 3;
|
|
63
|
-
const BLOCKHASH_FETCH_RETRY_SLEEP = 200;
|
|
64
|
-
const RECENT_BLOCKHASH_STALE_TIME_MS = 2_000; // Reuse blockhashes within this timeframe during bursts of tx contruction
|
|
65
|
-
|
|
66
|
-
/** Inputs to `TxHandler.buildTransaction`/`buildBulkTransactions` describing what to build and how. */
|
|
67
|
-
export type TxBuildingProps = {
|
|
68
|
-
instructions: TransactionInstruction | TransactionInstruction[];
|
|
69
|
-
/** `'legacy'` for a legacy `Transaction`, or `0` for a v0 `VersionedTransaction`. */
|
|
70
|
-
txVersion: TransactionVersion;
|
|
71
|
-
connection: Connection;
|
|
72
|
-
/** Commitment used when building/signing multiple legacy transactions via `getPreparedAndSignedLegacyTransactionMap`. */
|
|
73
|
-
preFlightCommitment?: Commitment;
|
|
74
|
-
/** Supplies the market address lookup tables to merge with `lookupTables` for a v0 transaction. */
|
|
75
|
-
fetchAllMarketLookupTableAccounts: () => Promise<AddressLookupTableAccount[]>;
|
|
76
|
-
/** Extra address lookup tables to compile the message against, in addition to the market ones from `fetchAllMarketLookupTableAccounts`. */
|
|
77
|
-
lookupTables?: AddressLookupTableAccount[];
|
|
78
|
-
/** If `true`, return a `VersionedTransaction` even when `txVersion === 'legacy'` (wraps the legacy message in a versioned envelope). */
|
|
79
|
-
forceVersionedTransaction?: boolean;
|
|
80
|
-
/** Compute-unit limit/price and simulation-based sizing options for this transaction. */
|
|
81
|
-
txParams?: TxParams;
|
|
82
|
-
/** Blockhash to use; if omitted, one is resolved via `TxHandler`'s `BlockhashFetcher`. */
|
|
83
|
-
recentBlockhash?: BlockhashWithExpiryBlockHeight;
|
|
84
|
-
wallet?: IWallet;
|
|
85
|
-
optionalIxs?: TransactionInstruction[]; // additional instructions to add to the front of ixs if there's enough room, such as oracle cranks
|
|
86
|
-
simulatedTx?: SimulatedTransactionResponse; // we could have pre-simulated the tx and we can use this later to get compute units
|
|
87
|
-
};
|
|
88
|
-
|
|
89
|
-
/** Configuration for `TxHandler`'s blockhash-fetching strategy. */
|
|
90
|
-
export type TxHandlerConfig = {
|
|
91
|
-
/** If `true`, use a `CachedBlockhashFetcher` (reduces RPC calls during bursts of tx construction); otherwise fetch fresh every time via `BaseBlockhashFetcher`. */
|
|
92
|
-
blockhashCachingEnabled?: boolean;
|
|
93
|
-
/** Tuning for `CachedBlockhashFetcher` when `blockhashCachingEnabled` is `true`; each field defaults if omitted (see `BLOCKHASH_FETCH_RETRY_COUNT`/`BLOCKHASH_FETCH_RETRY_SLEEP`/`RECENT_BLOCKHASH_STALE_TIME_MS`). */
|
|
94
|
-
blockhashCachingConfig?: {
|
|
95
|
-
retryCount?: number;
|
|
96
|
-
retrySleepTimeMs?: number;
|
|
97
|
-
staleCacheTimeMs?: number;
|
|
98
|
-
};
|
|
99
|
-
};
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* This class is responsible for creating and signing transactions.
|
|
103
|
-
*
|
|
104
|
-
* Owns blockhash resolution (via a `BlockhashFetcher`, optionally caching), compute-budget
|
|
105
|
-
* instruction injection, address-lookup-table compilation, and wallet signing for both legacy and
|
|
106
|
-
* v0 transactions, single or batched. `TxSender` implementations delegate to a `TxHandler`
|
|
107
|
-
* instance for all of this rather than duplicating it.
|
|
108
|
-
*/
|
|
109
|
-
export class TxHandler {
|
|
110
|
-
private blockHashToLastValidBlockHeightLookup: Record<string, number> = {};
|
|
111
|
-
private returnBlockHeightsWithSignedTxCallbackData = false;
|
|
112
|
-
|
|
113
|
-
private connection: Connection;
|
|
114
|
-
private wallet: IWallet;
|
|
115
|
-
private confirmationOptions: ConfirmOptions;
|
|
116
|
-
|
|
117
|
-
private preSignedCb?: () => void;
|
|
118
|
-
private onSignedCb?: (
|
|
119
|
-
txSigs: VelocityClientMetricsEvents['txSigned']
|
|
120
|
-
) => void;
|
|
121
|
-
|
|
122
|
-
private blockhashCommitment: Commitment =
|
|
123
|
-
DEFAULT_CONFIRMATION_OPTS.commitment ?? 'confirmed';
|
|
124
|
-
private blockHashFetcher: BlockhashFetcher;
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* @param props.connection - RPC connection used for blockhash fetches and (indirectly) sends.
|
|
128
|
-
* @param props.wallet - Default wallet used to sign transactions when a call doesn't pass its own.
|
|
129
|
-
* @param props.confirmationOptions - Default confirm options; `preflightCommitment` (falling
|
|
130
|
-
* back to `connection.commitment`, then `'confirmed'`) sets the commitment used for blockhash fetches.
|
|
131
|
-
* @param props.opts.returnBlockHeightsWithSignedTxCallbackData - If `true`, `onSignedCb` receives each signed tx's `lastValidBlockHeight` alongside its signature/blockhash.
|
|
132
|
-
* @param props.opts.onSignedCb - Callback invoked with signed-transaction metadata whenever this handler signs one or more transactions.
|
|
133
|
-
* @param props.opts.preSignedCb - Callback invoked immediately before wallet signing occurs.
|
|
134
|
-
* @param props.config - Blockhash-fetching strategy/tuning; see `TxHandlerConfig`.
|
|
135
|
-
*/
|
|
136
|
-
constructor(props: {
|
|
137
|
-
connection: Connection;
|
|
138
|
-
wallet: IWallet;
|
|
139
|
-
confirmationOptions: ConfirmOptions;
|
|
140
|
-
opts?: {
|
|
141
|
-
returnBlockHeightsWithSignedTxCallbackData?: boolean;
|
|
142
|
-
onSignedCb?: (txSigs: VelocityClientMetricsEvents['txSigned']) => void;
|
|
143
|
-
preSignedCb?: () => void;
|
|
144
|
-
};
|
|
145
|
-
config?: TxHandlerConfig;
|
|
146
|
-
}) {
|
|
147
|
-
this.connection = props.connection;
|
|
148
|
-
this.wallet = props.wallet;
|
|
149
|
-
this.confirmationOptions = props.confirmationOptions;
|
|
150
|
-
this.blockhashCommitment =
|
|
151
|
-
props.confirmationOptions?.preflightCommitment ??
|
|
152
|
-
props?.connection?.commitment ??
|
|
153
|
-
this.blockhashCommitment ??
|
|
154
|
-
'confirmed';
|
|
155
|
-
|
|
156
|
-
this.blockHashFetcher = props?.config?.blockhashCachingEnabled
|
|
157
|
-
? new CachedBlockhashFetcher(
|
|
158
|
-
this.connection,
|
|
159
|
-
this.blockhashCommitment,
|
|
160
|
-
props?.config?.blockhashCachingConfig?.retryCount ??
|
|
161
|
-
BLOCKHASH_FETCH_RETRY_COUNT,
|
|
162
|
-
props?.config?.blockhashCachingConfig?.retrySleepTimeMs ??
|
|
163
|
-
BLOCKHASH_FETCH_RETRY_SLEEP,
|
|
164
|
-
props?.config?.blockhashCachingConfig?.staleCacheTimeMs ??
|
|
165
|
-
RECENT_BLOCKHASH_STALE_TIME_MS
|
|
166
|
-
)
|
|
167
|
-
: new BaseBlockhashFetcher(this.connection, this.blockhashCommitment);
|
|
168
|
-
|
|
169
|
-
// #Optionals
|
|
170
|
-
this.returnBlockHeightsWithSignedTxCallbackData =
|
|
171
|
-
props.opts?.returnBlockHeightsWithSignedTxCallbackData ?? false;
|
|
172
|
-
this.onSignedCb = props.opts?.onSignedCb;
|
|
173
|
-
this.preSignedCb = props.opts?.preSignedCb;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
/** @returns The wallet this handler currently uses to sign transactions when a call doesn't pass its own. */
|
|
177
|
-
public getWallet() {
|
|
178
|
-
return this.wallet;
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
private addHashAndExpiryToLookup(
|
|
182
|
-
hashAndExpiry: BlockhashWithExpiryBlockHeight
|
|
183
|
-
) {
|
|
184
|
-
if (!this.returnBlockHeightsWithSignedTxCallbackData) return;
|
|
185
|
-
|
|
186
|
-
this.blockHashToLastValidBlockHeightLookup[hashAndExpiry.blockhash] =
|
|
187
|
-
hashAndExpiry.lastValidBlockHeight;
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
private getProps = (wallet?: IWallet, confirmationOpts?: ConfirmOptions) =>
|
|
191
|
-
[wallet ?? this.wallet, confirmationOpts ?? this.confirmationOptions] as [
|
|
192
|
-
IWallet,
|
|
193
|
-
ConfirmOptions,
|
|
194
|
-
];
|
|
195
|
-
|
|
196
|
-
/**
|
|
197
|
-
* Swaps the default wallet used for subsequent signing calls that don't pass their own.
|
|
198
|
-
* @param wallet - New default wallet.
|
|
199
|
-
*/
|
|
200
|
-
public updateWallet(wallet: IWallet) {
|
|
201
|
-
this.wallet = wallet;
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
/**
|
|
205
|
-
* Created this to prevent non-finalized blockhashes being used when building transactions. We want to always use finalized because otherwise it's easy to get the BlockHashNotFound error (RPC uses finalized to validate a transaction). Using an older blockhash when building transactions should never really be a problem right now.
|
|
206
|
-
*
|
|
207
|
-
* https://www.helius.dev/blog/how-to-deal-with-blockhash-errors-on-solana#why-do-blockhash-errors-occur
|
|
208
|
-
*
|
|
209
|
-
* @returns The latest blockhash (via this handler's configured `BlockhashFetcher`) at the
|
|
210
|
-
* commitment level resolved in the constructor, or `undefined` if unavailable.
|
|
211
|
-
*/
|
|
212
|
-
public async getLatestBlockhashForTransaction() {
|
|
213
|
-
return this.blockHashFetcher.getLatestBlockhash();
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
/**
|
|
217
|
-
* Resolves a usable recent blockhash, preferring a caller-provided one and
|
|
218
|
-
* otherwise fetching the latest. Throws if no blockhash can be obtained,
|
|
219
|
-
* since a transaction cannot be built or signed without one.
|
|
220
|
-
*/
|
|
221
|
-
private async resolveRecentBlockhash(
|
|
222
|
-
recentBlockhash?: BlockhashWithExpiryBlockHeight
|
|
223
|
-
): Promise<BlockhashWithExpiryBlockHeight> {
|
|
224
|
-
const resolved =
|
|
225
|
-
recentBlockhash ?? (await this.getLatestBlockhashForTransaction());
|
|
226
|
-
if (!resolved) {
|
|
227
|
-
throw new Error('TxHandler: failed to fetch a recent blockhash');
|
|
228
|
-
}
|
|
229
|
-
return resolved;
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
/**
|
|
233
|
-
* Applies recent blockhash and signs a given transaction. Attaches an internal
|
|
234
|
-
* `SIGNATURE_BLOCK_AND_EXPIRY` property (undocumented in the `Transaction` type, but read by
|
|
235
|
-
* `WhileValidTxSender`) recording the blockhash/expiry used, so confirmation logic can know
|
|
236
|
-
* when the transaction's blockhash has expired even for pre-built transactions.
|
|
237
|
-
* @param tx - Transaction to prepare; mutated in place (feePayer, recentBlockhash, signature).
|
|
238
|
-
* @param additionalSigners - Extra signers to co-sign alongside the wallet.
|
|
239
|
-
* @param wallet - Wallet to sign with; defaults to this handler's configured wallet.
|
|
240
|
-
* @param confirmationOpts - Unused directly here (present for interface symmetry with other overloads).
|
|
241
|
-
* @param preSigned - If `true`, return `tx` unchanged without touching blockhash/feePayer/signatures.
|
|
242
|
-
* @param recentBlockhash - Blockhash to use; if omitted, resolved via `getLatestBlockhashForTransaction`.
|
|
243
|
-
* @returns The prepared (and signed, unless `preSigned`) transaction.
|
|
244
|
-
* @throws Error if no blockhash could be resolved.
|
|
245
|
-
*/
|
|
246
|
-
public async prepareTx(
|
|
247
|
-
tx: Transaction,
|
|
248
|
-
additionalSigners: Array<Signer>,
|
|
249
|
-
wallet?: IWallet,
|
|
250
|
-
confirmationOpts?: ConfirmOptions,
|
|
251
|
-
preSigned?: boolean,
|
|
252
|
-
recentBlockhash?: BlockhashWithExpiryBlockHeight
|
|
253
|
-
): Promise<Transaction> {
|
|
254
|
-
if (preSigned) {
|
|
255
|
-
return tx;
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
[wallet, confirmationOpts] = this.getProps(wallet, confirmationOpts);
|
|
259
|
-
|
|
260
|
-
tx.feePayer = wallet.publicKey;
|
|
261
|
-
const resolvedBlockhash = await this.resolveRecentBlockhash(
|
|
262
|
-
recentBlockhash
|
|
263
|
-
);
|
|
264
|
-
tx.recentBlockhash = resolvedBlockhash.blockhash;
|
|
265
|
-
|
|
266
|
-
this.addHashAndExpiryToLookup(resolvedBlockhash);
|
|
267
|
-
|
|
268
|
-
const signedTx = await this.signTx(tx, additionalSigners);
|
|
269
|
-
|
|
270
|
-
// @ts-ignore
|
|
271
|
-
signedTx.SIGNATURE_BLOCK_AND_EXPIRY = resolvedBlockhash;
|
|
272
|
-
|
|
273
|
-
return signedTx;
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
private isVersionedTransaction(
|
|
277
|
-
tx: Transaction | VersionedTransaction
|
|
278
|
-
): boolean {
|
|
279
|
-
return isVersionedTransaction(tx);
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
private isLegacyTransaction(tx: Transaction | VersionedTransaction) {
|
|
283
|
-
return !this.isVersionedTransaction(tx);
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
private getTxSigFromSignedTx(signedTx: Transaction | VersionedTransaction) {
|
|
287
|
-
if (this.isVersionedTransaction(signedTx)) {
|
|
288
|
-
return bs58.encode(
|
|
289
|
-
Buffer.from((signedTx as VersionedTransaction).signatures[0])
|
|
290
|
-
) as string;
|
|
291
|
-
} else {
|
|
292
|
-
const signature = (signedTx as Transaction).signature;
|
|
293
|
-
if (!signature) {
|
|
294
|
-
throw new Error(
|
|
295
|
-
'TxHandler: cannot derive txSig from an unsigned legacy transaction'
|
|
296
|
-
);
|
|
297
|
-
}
|
|
298
|
-
return bs58.encode(Buffer.from(signature)) as string;
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
private getBlockhashFromSignedTx(
|
|
303
|
-
signedTx: Transaction | VersionedTransaction
|
|
304
|
-
): string {
|
|
305
|
-
const blockHash = this.isVersionedTransaction(signedTx)
|
|
306
|
-
? (signedTx as VersionedTransaction).message.recentBlockhash
|
|
307
|
-
: (signedTx as Transaction).recentBlockhash;
|
|
308
|
-
|
|
309
|
-
if (!blockHash) {
|
|
310
|
-
throw new Error(
|
|
311
|
-
'TxHandler: signed transaction is missing a recentBlockhash'
|
|
312
|
-
);
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
return blockHash;
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
private async signTx(
|
|
319
|
-
tx: Transaction,
|
|
320
|
-
additionalSigners: Array<Signer>,
|
|
321
|
-
wallet?: IWallet
|
|
322
|
-
): Promise<Transaction> {
|
|
323
|
-
[wallet] = this.getProps(wallet);
|
|
324
|
-
|
|
325
|
-
additionalSigners
|
|
326
|
-
.filter((s): s is Signer => s !== undefined)
|
|
327
|
-
.forEach((kp) => {
|
|
328
|
-
tx.partialSign(kp);
|
|
329
|
-
});
|
|
330
|
-
|
|
331
|
-
this.preSignedCb?.();
|
|
332
|
-
|
|
333
|
-
const signedTx = await wallet.signTransaction(tx);
|
|
334
|
-
|
|
335
|
-
// Turn txSig Buffer into base58 string
|
|
336
|
-
const txSig = this.getTxSigFromSignedTx(signedTx);
|
|
337
|
-
|
|
338
|
-
this.handleSignedTxData([
|
|
339
|
-
{
|
|
340
|
-
txSig,
|
|
341
|
-
signedTx,
|
|
342
|
-
blockHash: this.getBlockhashFromSignedTx(signedTx),
|
|
343
|
-
},
|
|
344
|
-
]);
|
|
345
|
-
|
|
346
|
-
return signedTx;
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
/**
|
|
350
|
-
* Signs a `VersionedTransaction`, optionally overwriting its blockhash first.
|
|
351
|
-
* @param tx - Transaction to sign; mutated in place.
|
|
352
|
-
* @param additionalSigners - Extra signers to co-sign alongside the wallet.
|
|
353
|
-
* @param recentBlockhash - If provided, overwrites `tx.message.recentBlockhash` before signing
|
|
354
|
-
* (and records it for `SIGNATURE_BLOCK_AND_EXPIRY` tracking); if omitted, the transaction's
|
|
355
|
-
* existing blockhash is used as-is.
|
|
356
|
-
* @param wallet - Wallet to sign with; defaults to this handler's configured wallet.
|
|
357
|
-
* @returns The signed transaction.
|
|
358
|
-
*/
|
|
359
|
-
public async signVersionedTx(
|
|
360
|
-
tx: VersionedTransaction,
|
|
361
|
-
additionalSigners: Array<Signer>,
|
|
362
|
-
recentBlockhash?: BlockhashWithExpiryBlockHeight,
|
|
363
|
-
wallet?: IWallet
|
|
364
|
-
): Promise<VersionedTransaction> {
|
|
365
|
-
[wallet] = this.getProps(wallet);
|
|
366
|
-
|
|
367
|
-
if (recentBlockhash) {
|
|
368
|
-
tx.message.recentBlockhash = recentBlockhash.blockhash;
|
|
369
|
-
|
|
370
|
-
this.addHashAndExpiryToLookup(recentBlockhash);
|
|
371
|
-
|
|
372
|
-
// @ts-ignore
|
|
373
|
-
tx.SIGNATURE_BLOCK_AND_EXPIRY = recentBlockhash;
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
additionalSigners
|
|
377
|
-
?.filter((s): s is Signer => s !== undefined)
|
|
378
|
-
.forEach((kp) => {
|
|
379
|
-
tx.sign([kp]);
|
|
380
|
-
});
|
|
381
|
-
|
|
382
|
-
this.preSignedCb?.();
|
|
383
|
-
|
|
384
|
-
//@ts-ignore
|
|
385
|
-
const signedTx = (await wallet.signTransaction(tx)) as VersionedTransaction;
|
|
386
|
-
|
|
387
|
-
// Turn txSig Buffer into base58 string
|
|
388
|
-
const txSig = this.getTxSigFromSignedTx(signedTx);
|
|
389
|
-
|
|
390
|
-
this.handleSignedTxData([
|
|
391
|
-
{
|
|
392
|
-
txSig,
|
|
393
|
-
signedTx,
|
|
394
|
-
blockHash: this.getBlockhashFromSignedTx(signedTx),
|
|
395
|
-
},
|
|
396
|
-
]);
|
|
397
|
-
|
|
398
|
-
return signedTx;
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
private handleSignedTxData(
|
|
402
|
-
txData: Omit<SignedTxData, 'lastValidBlockHeight'>[]
|
|
403
|
-
): SignedTxData[] {
|
|
404
|
-
if (!this.returnBlockHeightsWithSignedTxCallbackData) {
|
|
405
|
-
if (this.onSignedCb) {
|
|
406
|
-
this.onSignedCb(txData);
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
return [];
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
const signedTxData = txData.map((tx) => {
|
|
413
|
-
const lastValidBlockHeight =
|
|
414
|
-
this.blockHashToLastValidBlockHeightLookup[tx.blockHash];
|
|
415
|
-
|
|
416
|
-
return {
|
|
417
|
-
...tx,
|
|
418
|
-
lastValidBlockHeight,
|
|
419
|
-
};
|
|
420
|
-
});
|
|
421
|
-
|
|
422
|
-
if (this.onSignedCb) {
|
|
423
|
-
this.onSignedCb(signedTxData);
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
return signedTxData;
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
/**
|
|
430
|
-
* Gets transaction params with extra processing applied, like using the simulated compute units or using a dynamically calculated compute unit price.
|
|
431
|
-
* @param txBuildingProps
|
|
432
|
-
* @returns
|
|
433
|
-
*/
|
|
434
|
-
private async getProcessedTransactionParams(
|
|
435
|
-
txBuildingProps: TxBuildingProps
|
|
436
|
-
): Promise<BaseTxParams> {
|
|
437
|
-
const baseTxParams: BaseTxParams = {
|
|
438
|
-
computeUnits: txBuildingProps?.txParams?.computeUnits,
|
|
439
|
-
computeUnitsPrice: txBuildingProps?.txParams?.computeUnitsPrice,
|
|
440
|
-
};
|
|
441
|
-
|
|
442
|
-
const processedTxParams = await TransactionParamProcessor.process({
|
|
443
|
-
baseTxParams,
|
|
444
|
-
txBuilder: (updatedTxParams) =>
|
|
445
|
-
this.buildTransaction({
|
|
446
|
-
...txBuildingProps,
|
|
447
|
-
txParams: updatedTxParams.txParams ?? baseTxParams,
|
|
448
|
-
forceVersionedTransaction: true,
|
|
449
|
-
}) as Promise<VersionedTransaction>,
|
|
450
|
-
processConfig: {
|
|
451
|
-
useSimulatedComputeUnits:
|
|
452
|
-
txBuildingProps.txParams?.useSimulatedComputeUnits,
|
|
453
|
-
computeUnitsBufferMultiplier:
|
|
454
|
-
txBuildingProps.txParams?.computeUnitsBufferMultiplier,
|
|
455
|
-
useSimulatedComputeUnitsForCUPriceCalculation:
|
|
456
|
-
txBuildingProps.txParams
|
|
457
|
-
?.useSimulatedComputeUnitsForCUPriceCalculation,
|
|
458
|
-
getCUPriceFromComputeUnits:
|
|
459
|
-
txBuildingProps.txParams?.getCUPriceFromComputeUnits,
|
|
460
|
-
},
|
|
461
|
-
processParams: {
|
|
462
|
-
connection: this.connection,
|
|
463
|
-
simulatedTx: txBuildingProps.simulatedTx,
|
|
464
|
-
},
|
|
465
|
-
});
|
|
466
|
-
|
|
467
|
-
return processedTxParams;
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
private _generateVersionedTransaction(
|
|
471
|
-
recentBlockhash: BlockhashWithExpiryBlockHeight,
|
|
472
|
-
message: Message | MessageV0
|
|
473
|
-
) {
|
|
474
|
-
this.addHashAndExpiryToLookup(recentBlockhash);
|
|
475
|
-
|
|
476
|
-
return new VersionedTransaction(message);
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
/**
|
|
480
|
-
* Builds an unsigned `VersionedTransaction` that wraps a *legacy* compiled message (no address
|
|
481
|
-
* lookup tables) — used when `forceVersionedTransaction` is requested for a `'legacy'`
|
|
482
|
-
* `txVersion`.
|
|
483
|
-
* @param recentBlockhash - Blockhash to build the message with.
|
|
484
|
-
* @param ixs - Instructions to include, in order.
|
|
485
|
-
* @param wallet - Wallet whose pubkey becomes the fee payer; defaults to this handler's configured wallet.
|
|
486
|
-
* @returns The unsigned `VersionedTransaction`.
|
|
487
|
-
*/
|
|
488
|
-
public generateLegacyVersionedTransaction(
|
|
489
|
-
recentBlockhash: BlockhashWithExpiryBlockHeight,
|
|
490
|
-
ixs: TransactionInstruction[],
|
|
491
|
-
wallet?: IWallet
|
|
492
|
-
) {
|
|
493
|
-
[wallet] = this.getProps(wallet);
|
|
494
|
-
|
|
495
|
-
const message = new TransactionMessage({
|
|
496
|
-
payerKey: wallet.publicKey,
|
|
497
|
-
recentBlockhash: recentBlockhash.blockhash,
|
|
498
|
-
instructions: ixs,
|
|
499
|
-
}).compileToLegacyMessage();
|
|
500
|
-
|
|
501
|
-
const tx = this._generateVersionedTransaction(recentBlockhash, message);
|
|
502
|
-
|
|
503
|
-
// @ts-ignore
|
|
504
|
-
tx.SIGNATURE_BLOCK_AND_EXPIRY = recentBlockhash;
|
|
505
|
-
|
|
506
|
-
return tx;
|
|
507
|
-
}
|
|
508
|
-
|
|
509
|
-
/**
|
|
510
|
-
* Builds an unsigned v0 `VersionedTransaction`, compiling its message against the given
|
|
511
|
-
* address lookup tables.
|
|
512
|
-
* @param recentBlockhash - Blockhash to build the message with.
|
|
513
|
-
* @param ixs - Instructions to include, in order.
|
|
514
|
-
* @param lookupTableAccounts - Address lookup tables to compile the message against.
|
|
515
|
-
* @param wallet - Wallet whose pubkey becomes the fee payer; defaults to this handler's configured wallet.
|
|
516
|
-
* @returns The unsigned `VersionedTransaction`.
|
|
517
|
-
*/
|
|
518
|
-
public generateVersionedTransaction(
|
|
519
|
-
recentBlockhash: BlockhashWithExpiryBlockHeight,
|
|
520
|
-
ixs: TransactionInstruction[],
|
|
521
|
-
lookupTableAccounts: AddressLookupTableAccount[],
|
|
522
|
-
wallet?: IWallet
|
|
523
|
-
) {
|
|
524
|
-
[wallet] = this.getProps(wallet);
|
|
525
|
-
|
|
526
|
-
const message = new TransactionMessage({
|
|
527
|
-
payerKey: wallet.publicKey,
|
|
528
|
-
recentBlockhash: recentBlockhash.blockhash,
|
|
529
|
-
instructions: ixs,
|
|
530
|
-
}).compileToV0Message(lookupTableAccounts);
|
|
531
|
-
|
|
532
|
-
const tx = this._generateVersionedTransaction(recentBlockhash, message);
|
|
533
|
-
|
|
534
|
-
// @ts-ignore
|
|
535
|
-
tx.SIGNATURE_BLOCK_AND_EXPIRY = recentBlockhash;
|
|
536
|
-
|
|
537
|
-
return tx;
|
|
538
|
-
}
|
|
539
|
-
|
|
540
|
-
/**
|
|
541
|
-
* Builds an unsigned legacy `Transaction` from raw instructions. Unlike the other `generate*`
|
|
542
|
-
* methods, this does not set a fee payer.
|
|
543
|
-
* @param ixs - Instructions to include, in order.
|
|
544
|
-
* @param recentBlockhash - If provided, sets `tx.recentBlockhash`; otherwise left unset.
|
|
545
|
-
* @returns The unsigned `Transaction`.
|
|
546
|
-
*/
|
|
547
|
-
public generateLegacyTransaction(
|
|
548
|
-
ixs: TransactionInstruction[],
|
|
549
|
-
recentBlockhash?: BlockhashWithExpiryBlockHeight
|
|
550
|
-
) {
|
|
551
|
-
const tx = new Transaction().add(...ixs);
|
|
552
|
-
if (recentBlockhash) {
|
|
553
|
-
tx.recentBlockhash = recentBlockhash.blockhash;
|
|
554
|
-
}
|
|
555
|
-
return tx;
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
/**
|
|
559
|
-
* Accepts multiple instructions and builds a transaction for each. Prevents needing to spam RPC with requests for the same blockhash.
|
|
560
|
-
* @param props - Shared `TxBuildingProps` (minus `instructions`) plus one instruction/array
|
|
561
|
-
* per output transaction; a falsy entry in `props.instructions` yields `undefined` at that
|
|
562
|
-
* position rather than being built.
|
|
563
|
-
* @returns One built transaction (or `undefined`) per entry in `props.instructions`, in the same order.
|
|
564
|
-
*/
|
|
565
|
-
public async buildBulkTransactions(
|
|
566
|
-
props: Omit<TxBuildingProps, 'instructions'> & {
|
|
567
|
-
instructions: (TransactionInstruction | TransactionInstruction[])[];
|
|
568
|
-
}
|
|
569
|
-
) {
|
|
570
|
-
const recentBlockhash = await this.resolveRecentBlockhash(
|
|
571
|
-
props?.recentBlockhash
|
|
572
|
-
);
|
|
573
|
-
|
|
574
|
-
return await Promise.all(
|
|
575
|
-
props.instructions.map((ix) => {
|
|
576
|
-
if (!ix) return undefined;
|
|
577
|
-
return this.buildTransaction({
|
|
578
|
-
...props,
|
|
579
|
-
instructions: ix,
|
|
580
|
-
recentBlockhash,
|
|
581
|
-
});
|
|
582
|
-
})
|
|
583
|
-
);
|
|
584
|
-
}
|
|
585
|
-
|
|
586
|
-
/**
|
|
587
|
-
* Builds a full transaction from raw instructions: merges caller-supplied `lookupTables` with
|
|
588
|
-
* the market lookup tables from `fetchAllMarketLookupTableAccounts`, optionally appends as many
|
|
589
|
-
* `optionalIxs` (e.g. oracle cranks) as fit under `MAX_TX_BYTE_SIZE` (dropped one-by-one and
|
|
590
|
-
* re-simulated if the batch fails simulation), resolves compute-unit limit/price (via
|
|
591
|
-
* simulation if `txParams.useSimulatedComputeUnits`), and prepends the resulting
|
|
592
|
-
* `ComputeBudgetProgram` instructions unless the caller's instructions already include them.
|
|
593
|
-
* @param props - See `TxBuildingProps`. `props.forceVersionedTransaction` returns a
|
|
594
|
-
* `VersionedTransaction` instance even if `props.txVersion` is `'legacy'`.
|
|
595
|
-
* @returns The built transaction — a `Transaction` for `txVersion === 'legacy'` unless
|
|
596
|
-
* `forceVersionedTransaction` is set, otherwise a `VersionedTransaction`. Not yet signed.
|
|
597
|
-
*/
|
|
598
|
-
public async buildTransaction(
|
|
599
|
-
props: TxBuildingProps
|
|
600
|
-
): Promise<Transaction | VersionedTransaction> {
|
|
601
|
-
const {
|
|
602
|
-
txVersion,
|
|
603
|
-
txParams,
|
|
604
|
-
connection: _connection,
|
|
605
|
-
preFlightCommitment: _preFlightCommitment,
|
|
606
|
-
fetchAllMarketLookupTableAccounts,
|
|
607
|
-
forceVersionedTransaction,
|
|
608
|
-
instructions,
|
|
609
|
-
} = props;
|
|
610
|
-
|
|
611
|
-
let { lookupTables } = props;
|
|
612
|
-
|
|
613
|
-
const marketLookupTables = await fetchAllMarketLookupTableAccounts();
|
|
614
|
-
|
|
615
|
-
// Combine and filter out any null/undefined lookup tables
|
|
616
|
-
const combinedLookupTables = lookupTables
|
|
617
|
-
? [...lookupTables, ...marketLookupTables]
|
|
618
|
-
: marketLookupTables;
|
|
619
|
-
lookupTables = combinedLookupTables.filter(
|
|
620
|
-
(table): table is AddressLookupTableAccount =>
|
|
621
|
-
table !== null && table !== undefined
|
|
622
|
-
);
|
|
623
|
-
|
|
624
|
-
// # Collect and process Tx Params
|
|
625
|
-
let baseTxParams: BaseTxParams = {
|
|
626
|
-
computeUnits: txParams?.computeUnits,
|
|
627
|
-
computeUnitsPrice: txParams?.computeUnitsPrice,
|
|
628
|
-
};
|
|
629
|
-
|
|
630
|
-
const instructionsArray = Array.isArray(instructions)
|
|
631
|
-
? instructions
|
|
632
|
-
: [instructions];
|
|
633
|
-
|
|
634
|
-
let instructionsToUse: TransactionInstruction[];
|
|
635
|
-
let simulatedTx: SimulatedTransactionResponse | undefined;
|
|
636
|
-
// add optional ixs if there's room and it doesn't fail simulation (usually oracle cranks)
|
|
637
|
-
if (props.optionalIxs && txVersion === 0) {
|
|
638
|
-
[instructionsToUse, simulatedTx] =
|
|
639
|
-
await this.simulateAndCalculateInstructions(
|
|
640
|
-
{
|
|
641
|
-
...props,
|
|
642
|
-
instructions: instructionsArray,
|
|
643
|
-
txVersion,
|
|
644
|
-
lookupTables,
|
|
645
|
-
},
|
|
646
|
-
props.optionalIxs,
|
|
647
|
-
txVersion === 0,
|
|
648
|
-
lookupTables
|
|
649
|
-
);
|
|
650
|
-
} else {
|
|
651
|
-
instructionsToUse = instructionsArray;
|
|
652
|
-
}
|
|
653
|
-
|
|
654
|
-
if (txParams?.useSimulatedComputeUnits) {
|
|
655
|
-
const processedTxParams = await this.getProcessedTransactionParams({
|
|
656
|
-
...props,
|
|
657
|
-
instructions: instructionsToUse,
|
|
658
|
-
simulatedTx: simulatedTx,
|
|
659
|
-
});
|
|
660
|
-
|
|
661
|
-
baseTxParams = {
|
|
662
|
-
...baseTxParams,
|
|
663
|
-
...processedTxParams,
|
|
664
|
-
};
|
|
665
|
-
}
|
|
666
|
-
|
|
667
|
-
const { hasSetComputeUnitLimitIx, hasSetComputeUnitPriceIx } =
|
|
668
|
-
containsComputeUnitIxs(instructionsToUse);
|
|
669
|
-
|
|
670
|
-
// # Create Tx Instructions
|
|
671
|
-
const allIx = [];
|
|
672
|
-
const computeUnits = baseTxParams?.computeUnits;
|
|
673
|
-
if (
|
|
674
|
-
computeUnits !== undefined &&
|
|
675
|
-
computeUnits > 0 &&
|
|
676
|
-
!hasSetComputeUnitLimitIx
|
|
677
|
-
) {
|
|
678
|
-
allIx.push(
|
|
679
|
-
ComputeBudgetProgram.setComputeUnitLimit({
|
|
680
|
-
units: computeUnits,
|
|
681
|
-
})
|
|
682
|
-
);
|
|
683
|
-
}
|
|
684
|
-
|
|
685
|
-
const computeUnitsPrice = baseTxParams?.computeUnitsPrice;
|
|
686
|
-
|
|
687
|
-
if (DEV_TRY_FORCE_TX_TIMEOUTS) {
|
|
688
|
-
allIx.push(
|
|
689
|
-
ComputeBudgetProgram.setComputeUnitPrice({
|
|
690
|
-
microLamports: 0,
|
|
691
|
-
})
|
|
692
|
-
);
|
|
693
|
-
} else if (
|
|
694
|
-
computeUnitsPrice !== undefined &&
|
|
695
|
-
computeUnitsPrice > 0 &&
|
|
696
|
-
!hasSetComputeUnitPriceIx
|
|
697
|
-
) {
|
|
698
|
-
allIx.push(
|
|
699
|
-
ComputeBudgetProgram.setComputeUnitPrice({
|
|
700
|
-
microLamports: computeUnitsPrice,
|
|
701
|
-
})
|
|
702
|
-
);
|
|
703
|
-
}
|
|
704
|
-
|
|
705
|
-
allIx.push(...instructionsToUse);
|
|
706
|
-
|
|
707
|
-
const recentBlockhash = await this.resolveRecentBlockhash(
|
|
708
|
-
props?.recentBlockhash
|
|
709
|
-
);
|
|
710
|
-
|
|
711
|
-
// # Create and return Transaction
|
|
712
|
-
if (txVersion === 'legacy') {
|
|
713
|
-
if (forceVersionedTransaction) {
|
|
714
|
-
return this.generateLegacyVersionedTransaction(recentBlockhash, allIx);
|
|
715
|
-
} else {
|
|
716
|
-
return this.generateLegacyTransaction(allIx, recentBlockhash);
|
|
717
|
-
}
|
|
718
|
-
} else {
|
|
719
|
-
return this.generateVersionedTransaction(
|
|
720
|
-
recentBlockhash,
|
|
721
|
-
allIx,
|
|
722
|
-
lookupTables
|
|
723
|
-
);
|
|
724
|
-
}
|
|
725
|
-
}
|
|
726
|
-
|
|
727
|
-
/**
|
|
728
|
-
* Wraps a single instruction in a legacy `Transaction`, prepending compute-budget instructions
|
|
729
|
-
* as needed. Does not set a blockhash or fee payer.
|
|
730
|
-
* @param instruction - Instruction to wrap.
|
|
731
|
-
* @param computeUnits - Compute unit limit; defaults to 600,000. A `setComputeUnitLimit`
|
|
732
|
-
* instruction is added unless this value equals `COMPUTE_UNITS_DEFAULT` (200,000) exactly —
|
|
733
|
-
* note the 600,000 default therefore *does* add one.
|
|
734
|
-
* @param computeUnitsPrice - Compute unit price in micro-lamports; defaults to 0, in which case
|
|
735
|
-
* no `setComputeUnitPrice` instruction is added.
|
|
736
|
-
* @returns The unsigned `Transaction`.
|
|
737
|
-
*/
|
|
738
|
-
public wrapInTx(
|
|
739
|
-
instruction: TransactionInstruction,
|
|
740
|
-
computeUnits = 600_000,
|
|
741
|
-
computeUnitsPrice = 0
|
|
742
|
-
): Transaction {
|
|
743
|
-
const tx = new Transaction();
|
|
744
|
-
if (computeUnits != COMPUTE_UNITS_DEFAULT) {
|
|
745
|
-
tx.add(
|
|
746
|
-
ComputeBudgetProgram.setComputeUnitLimit({
|
|
747
|
-
units: computeUnits,
|
|
748
|
-
})
|
|
749
|
-
);
|
|
750
|
-
}
|
|
751
|
-
|
|
752
|
-
if (DEV_TRY_FORCE_TX_TIMEOUTS) {
|
|
753
|
-
tx.add(
|
|
754
|
-
ComputeBudgetProgram.setComputeUnitPrice({
|
|
755
|
-
microLamports: 0,
|
|
756
|
-
})
|
|
757
|
-
);
|
|
758
|
-
} else if (computeUnitsPrice != 0) {
|
|
759
|
-
tx.add(
|
|
760
|
-
ComputeBudgetProgram.setComputeUnitPrice({
|
|
761
|
-
microLamports: computeUnitsPrice,
|
|
762
|
-
})
|
|
763
|
-
);
|
|
764
|
-
}
|
|
765
|
-
|
|
766
|
-
return tx.add(instruction);
|
|
767
|
-
}
|
|
768
|
-
|
|
769
|
-
/**
|
|
770
|
-
* Get a map of signed and prepared transactions from an array of legacy transactions
|
|
771
|
-
* @param txsMap - Map of key to legacy `Transaction` (or `undefined`, passed through unset); each is mutated with blockhash/feePayer before signing.
|
|
772
|
-
* @param wallet - Wallet to sign with; defaults to this handler's configured wallet.
|
|
773
|
-
* @param commitment - Unused directly here (accepted for interface symmetry with `TxSender.send`-style callers).
|
|
774
|
-
* @param recentBlockhash - Blockhash to apply to every transaction in `txsMap`; if omitted, resolved via `getLatestBlockhashForTransaction`.
|
|
775
|
-
* @returns `{ signedTxMap, signedTxData }` — see `getSignedTransactionMap`.
|
|
776
|
-
* @throws Error if no blockhash could be resolved.
|
|
777
|
-
*/
|
|
778
|
-
public async getPreparedAndSignedLegacyTransactionMap<
|
|
779
|
-
T extends Record<string, Transaction | undefined>,
|
|
780
|
-
>(
|
|
781
|
-
txsMap: T,
|
|
782
|
-
wallet?: IWallet,
|
|
783
|
-
commitment?: Commitment,
|
|
784
|
-
recentBlockhash?: BlockhashWithExpiryBlockHeight
|
|
785
|
-
) {
|
|
786
|
-
const resolvedBlockhash = await this.resolveRecentBlockhash(
|
|
787
|
-
recentBlockhash
|
|
788
|
-
);
|
|
789
|
-
|
|
790
|
-
this.addHashAndExpiryToLookup(resolvedBlockhash);
|
|
791
|
-
|
|
792
|
-
for (const tx of Object.values(txsMap)) {
|
|
793
|
-
if (!tx) continue;
|
|
794
|
-
tx.recentBlockhash = resolvedBlockhash.blockhash;
|
|
795
|
-
tx.feePayer = wallet?.publicKey ?? this.wallet?.publicKey;
|
|
796
|
-
|
|
797
|
-
// @ts-ignore
|
|
798
|
-
tx.SIGNATURE_BLOCK_AND_EXPIRY = resolvedBlockhash;
|
|
799
|
-
}
|
|
800
|
-
|
|
801
|
-
return this.getSignedTransactionMap(txsMap, wallet);
|
|
802
|
-
}
|
|
803
|
-
|
|
804
|
-
/**
|
|
805
|
-
* Get a map of signed transactions from an array of transactions to sign. Signs all non-`undefined`
|
|
806
|
-
* entries in a single `wallet.signAllTransactions` batch (one wallet approval for the whole map,
|
|
807
|
-
* where the wallet supports it) rather than one signature request per transaction.
|
|
808
|
-
* @param txsToSignMap - Map of key to `Transaction`/`VersionedTransaction` (or `undefined`,
|
|
809
|
-
* passed through as `undefined` in the result rather than being signed).
|
|
810
|
-
* @param wallet - Wallet to sign with; defaults to this handler's configured wallet.
|
|
811
|
-
* @returns `signedTxMap` — same keys as the input, with each defined entry replaced by its
|
|
812
|
-
* signed transaction; and `signedTxData` — the per-transaction signature/blockhash metadata
|
|
813
|
-
* (with `lastValidBlockHeight` if this handler was configured with
|
|
814
|
-
* `returnBlockHeightsWithSignedTxCallbackData`), also passed to `onSignedCb` if configured.
|
|
815
|
-
*/
|
|
816
|
-
public async getSignedTransactionMap<
|
|
817
|
-
T extends Record<string, Transaction | VersionedTransaction | undefined>,
|
|
818
|
-
>(
|
|
819
|
-
txsToSignMap: T,
|
|
820
|
-
wallet?: IWallet
|
|
821
|
-
): Promise<{
|
|
822
|
-
signedTxMap: T;
|
|
823
|
-
signedTxData: SignedTxData[];
|
|
824
|
-
}> {
|
|
825
|
-
[wallet] = this.getProps(wallet);
|
|
826
|
-
|
|
827
|
-
const txsToSignEntries = Object.entries(txsToSignMap);
|
|
828
|
-
|
|
829
|
-
// Create a map of the same keys as the input map, but with the values set to undefined. We'll populate the filtered (non-undefined) values with signed transactions.
|
|
830
|
-
const signedTxMap = txsToSignEntries.reduce(
|
|
831
|
-
(acc, [key]) => {
|
|
832
|
-
acc[key] = undefined;
|
|
833
|
-
return acc;
|
|
834
|
-
},
|
|
835
|
-
{} as Record<string, Transaction | VersionedTransaction | undefined>
|
|
836
|
-
) as T;
|
|
837
|
-
|
|
838
|
-
const filteredTxEntries = txsToSignEntries.filter(
|
|
839
|
-
(entry): entry is [string, Transaction | VersionedTransaction] =>
|
|
840
|
-
!!entry[1]
|
|
841
|
-
);
|
|
842
|
-
|
|
843
|
-
// Extra handling for legacy transactions
|
|
844
|
-
for (const [_key, tx] of filteredTxEntries) {
|
|
845
|
-
if (this.isLegacyTransaction(tx)) {
|
|
846
|
-
(tx as Transaction).feePayer = wallet.publicKey;
|
|
847
|
-
}
|
|
848
|
-
}
|
|
849
|
-
|
|
850
|
-
this.preSignedCb?.();
|
|
851
|
-
|
|
852
|
-
const signedFilteredTxs = await wallet.signAllTransactions(
|
|
853
|
-
filteredTxEntries.map(([_, tx]) => tx as Transaction)
|
|
854
|
-
);
|
|
855
|
-
|
|
856
|
-
signedFilteredTxs.forEach((signedTx, index) => {
|
|
857
|
-
// @ts-ignore
|
|
858
|
-
signedTx.SIGNATURE_BLOCK_AND_EXPIRY =
|
|
859
|
-
// @ts-ignore
|
|
860
|
-
filteredTxEntries[index][1]?.SIGNATURE_BLOCK_AND_EXPIRY;
|
|
861
|
-
});
|
|
862
|
-
|
|
863
|
-
const signedTxData = this.handleSignedTxData(
|
|
864
|
-
signedFilteredTxs.map((signedTx) => {
|
|
865
|
-
return {
|
|
866
|
-
txSig: this.getTxSigFromSignedTx(signedTx),
|
|
867
|
-
signedTx,
|
|
868
|
-
blockHash: this.getBlockhashFromSignedTx(signedTx),
|
|
869
|
-
};
|
|
870
|
-
})
|
|
871
|
-
);
|
|
872
|
-
|
|
873
|
-
filteredTxEntries.forEach(([key], index) => {
|
|
874
|
-
const signedTx = signedFilteredTxs[index];
|
|
875
|
-
// @ts-ignore
|
|
876
|
-
signedTxMap[key] = signedTx;
|
|
877
|
-
});
|
|
878
|
-
|
|
879
|
-
return { signedTxMap, signedTxData };
|
|
880
|
-
}
|
|
881
|
-
|
|
882
|
-
/**
|
|
883
|
-
* Accepts multiple instructions and builds a transaction for each. Prevents needing to spam RPC with requests for the same blockhash.
|
|
884
|
-
* @param props - Shared `TxBuildingProps` (minus `instructions`) plus a named map of instruction(s) per output transaction.
|
|
885
|
-
* @returns A map with the same keys as `props.instructionsMap`, each value the corresponding built transaction.
|
|
886
|
-
*/
|
|
887
|
-
public async buildTransactionsMap<
|
|
888
|
-
T extends Record<string, TransactionInstruction | TransactionInstruction[]>,
|
|
889
|
-
>(
|
|
890
|
-
props: Omit<TxBuildingProps, 'instructions'> & {
|
|
891
|
-
instructionsMap: T;
|
|
892
|
-
}
|
|
893
|
-
): Promise<MappedRecord<T, Transaction | VersionedTransaction>> {
|
|
894
|
-
const builtTxs = await this.buildBulkTransactions({
|
|
895
|
-
...props,
|
|
896
|
-
instructions: Object.values(props.instructionsMap),
|
|
897
|
-
});
|
|
898
|
-
|
|
899
|
-
return Object.keys(props.instructionsMap).reduce(
|
|
900
|
-
(acc, key, index) => {
|
|
901
|
-
acc[key] = builtTxs[index];
|
|
902
|
-
return acc;
|
|
903
|
-
},
|
|
904
|
-
{} as Record<string, Transaction | VersionedTransaction | undefined>
|
|
905
|
-
) as MappedRecord<T, Transaction | VersionedTransaction>;
|
|
906
|
-
}
|
|
907
|
-
|
|
908
|
-
/**
|
|
909
|
-
* Builds and signs transactions from a given array of instructions for multiple transactions.
|
|
910
|
-
* Builds every transaction first (`buildTransactionsMap`), then signs them all in one batch —
|
|
911
|
-
* via `getPreparedAndSignedLegacyTransactionMap` for `'legacy'` `txVersion`, otherwise
|
|
912
|
-
* `getSignedTransactionMap`.
|
|
913
|
-
* @param props - Shared `TxBuildingProps` (minus `instructions`) plus a named map of instruction(s) per output transaction.
|
|
914
|
-
* @returns `{ signedTxMap, signedTxData }` keyed the same as `props.instructionsMap`; see `getSignedTransactionMap`.
|
|
915
|
-
*/
|
|
916
|
-
public async buildAndSignTransactionMap<
|
|
917
|
-
T extends Record<string, TransactionInstruction | TransactionInstruction[]>,
|
|
918
|
-
>(
|
|
919
|
-
props: Omit<TxBuildingProps, 'instructions'> & {
|
|
920
|
-
instructionsMap: T;
|
|
921
|
-
}
|
|
922
|
-
) {
|
|
923
|
-
const builtTxs = await this.buildTransactionsMap(props);
|
|
924
|
-
|
|
925
|
-
const preppedTransactions = await (props.txVersion === 'legacy'
|
|
926
|
-
? this.getPreparedAndSignedLegacyTransactionMap(
|
|
927
|
-
builtTxs as Record<string, Transaction>,
|
|
928
|
-
props.wallet,
|
|
929
|
-
props.preFlightCommitment
|
|
930
|
-
)
|
|
931
|
-
: this.getSignedTransactionMap(builtTxs, props.wallet));
|
|
932
|
-
|
|
933
|
-
return preppedTransactions;
|
|
934
|
-
}
|
|
935
|
-
|
|
936
|
-
/**
|
|
937
|
-
* Greedily includes as many `optionalInstructions` (e.g. oracle-crank instructions) as fit
|
|
938
|
-
* alongside `txBuildingProps.instructions` under `MAX_TX_BYTE_SIZE`, then simulates the result;
|
|
939
|
-
* if simulation fails, falls back to simulating with only the base instructions (optional ones
|
|
940
|
-
* dropped entirely) rather than trying to isolate which optional instruction caused the failure.
|
|
941
|
-
* @param txBuildingProps - Build props whose `instructions` are the required (non-optional) instructions.
|
|
942
|
-
* @param optionalInstructions - Extra instructions to include only if they fit; prepended
|
|
943
|
-
* ahead of the base instructions and trimmed one-by-one from the front if the combined size
|
|
944
|
-
* exceeds `MAX_TX_BYTE_SIZE`. Defaults to none, in which case this is a no-op passthrough.
|
|
945
|
-
* @param versionedTransaction - Whether to size the candidate transaction as versioned (v0) or legacy; defaults to `true`.
|
|
946
|
-
* @param addressLookupTables - Lookup tables credited toward the size calculation; defaults to none.
|
|
947
|
-
* @returns A tuple of `[instructionsActuallyUsed, simulationResult]` — `instructionsActuallyUsed`
|
|
948
|
-
* includes the optional instructions only if the combined simulation succeeded; `simulationResult`
|
|
949
|
-
* is `undefined` only when `optionalInstructions` was empty (no simulation was needed).
|
|
950
|
-
*/
|
|
951
|
-
public async simulateAndCalculateInstructions(
|
|
952
|
-
txBuildingProps: TxBuildingProps,
|
|
953
|
-
optionalInstructions: TransactionInstruction[] = [],
|
|
954
|
-
versionedTransaction = true,
|
|
955
|
-
addressLookupTables: AddressLookupTableAccount[] = []
|
|
956
|
-
): Promise<
|
|
957
|
-
[TransactionInstruction[], SimulatedTransactionResponse | undefined]
|
|
958
|
-
> {
|
|
959
|
-
const baseInstructions = Array.isArray(txBuildingProps.instructions)
|
|
960
|
-
? txBuildingProps.instructions
|
|
961
|
-
: [txBuildingProps.instructions];
|
|
962
|
-
if (optionalInstructions.length === 0) {
|
|
963
|
-
return [baseInstructions, undefined];
|
|
964
|
-
}
|
|
965
|
-
|
|
966
|
-
let allInstructions = [...optionalInstructions, ...baseInstructions];
|
|
967
|
-
|
|
968
|
-
let txSize = getSizeOfTransaction(
|
|
969
|
-
allInstructions,
|
|
970
|
-
versionedTransaction,
|
|
971
|
-
addressLookupTables
|
|
972
|
-
);
|
|
973
|
-
|
|
974
|
-
while (
|
|
975
|
-
txSize > MAX_TX_BYTE_SIZE &&
|
|
976
|
-
allInstructions.length > baseInstructions.length
|
|
977
|
-
) {
|
|
978
|
-
allInstructions = allInstructions.slice(1);
|
|
979
|
-
txSize = getSizeOfTransaction(
|
|
980
|
-
allInstructions,
|
|
981
|
-
versionedTransaction,
|
|
982
|
-
addressLookupTables
|
|
983
|
-
);
|
|
984
|
-
}
|
|
985
|
-
|
|
986
|
-
const tx = await this.buildTransaction({
|
|
987
|
-
...txBuildingProps,
|
|
988
|
-
optionalIxs: undefined,
|
|
989
|
-
instructions: allInstructions,
|
|
990
|
-
});
|
|
991
|
-
|
|
992
|
-
const simulatedTx = await this.connection.simulateTransaction(
|
|
993
|
-
tx as VersionedTransaction
|
|
994
|
-
);
|
|
995
|
-
|
|
996
|
-
if (simulatedTx.value?.err) {
|
|
997
|
-
const tx = await this.buildTransaction({
|
|
998
|
-
...txBuildingProps,
|
|
999
|
-
optionalIxs: undefined,
|
|
1000
|
-
instructions: baseInstructions,
|
|
1001
|
-
});
|
|
1002
|
-
const simulationWithoutOptionalIxs =
|
|
1003
|
-
await this.connection.simulateTransaction(tx as VersionedTransaction);
|
|
1004
|
-
return [baseInstructions, simulationWithoutOptionalIxs.value];
|
|
1005
|
-
}
|
|
1006
|
-
|
|
1007
|
-
return [allInstructions, simulatedTx.value];
|
|
1008
|
-
}
|
|
1009
|
-
}
|