@velocity-exchange/sdk 0.4.0 → 0.6.1
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 +52 -0
- package/lib/browser/adminClient.js +97 -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 +191 -15
- package/lib/browser/idl/velocity.json +192 -16
- package/lib/browser/orderSubscriber/OrderSubscriber.d.ts +1 -0
- package/lib/browser/orderSubscriber/OrderSubscriber.js +10 -4
- package/lib/browser/pyth/pythLazerSubscriber.js +37 -27
- package/lib/browser/types.d.ts +6 -0
- package/lib/browser/user.d.ts +20 -3
- package/lib/browser/user.js +52 -4
- package/lib/browser/velocityClient.d.ts +46 -10
- package/lib/browser/velocityClient.js +107 -35
- package/lib/node/adminClient.d.ts +52 -0
- package/lib/node/adminClient.d.ts.map +1 -1
- package/lib/node/adminClient.js +97 -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 +191 -15
- package/lib/node/idl/velocity.d.ts.map +1 -1
- package/lib/node/idl/velocity.json +192 -16
- package/lib/node/orderSubscriber/OrderSubscriber.d.ts +1 -0
- package/lib/node/orderSubscriber/OrderSubscriber.d.ts.map +1 -1
- package/lib/node/orderSubscriber/OrderSubscriber.js +10 -4
- package/lib/node/pyth/pythLazerSubscriber.d.ts.map +1 -1
- package/lib/node/pyth/pythLazerSubscriber.js +37 -27
- package/lib/node/types.d.ts +6 -0
- package/lib/node/types.d.ts.map +1 -1
- package/lib/node/user.d.ts +20 -3
- package/lib/node/user.d.ts.map +1 -1
- package/lib/node/user.js +52 -4
- 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
|
@@ -1,333 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Connection,
|
|
3
|
-
Context,
|
|
4
|
-
RpcResponseAndContext,
|
|
5
|
-
SignatureResult,
|
|
6
|
-
SignatureStatus,
|
|
7
|
-
TransactionConfirmationStatus,
|
|
8
|
-
} from '@solana/web3.js';
|
|
9
|
-
import { DEFAULT_CONFIRMATION_OPTS } from '../config';
|
|
10
|
-
import { TxSendError } from '../tx/types';
|
|
11
|
-
import { NOT_CONFIRMED_ERROR_CODE } from '../constants/txConstants';
|
|
12
|
-
import {
|
|
13
|
-
getTransactionErrorFromTxSig,
|
|
14
|
-
throwTransactionError,
|
|
15
|
-
} from '../tx/reportTransactionError';
|
|
16
|
-
import { promiseTimeout } from './promiseTimeout';
|
|
17
|
-
import { ClientSubscriptionId } from '../bankrun/bankrunConnection';
|
|
18
|
-
|
|
19
|
-
type ResolveReference = {
|
|
20
|
-
resolve?: () => void;
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
const confirmationStatusValues: Record<TransactionConfirmationStatus, number> =
|
|
24
|
-
{
|
|
25
|
-
processed: 0,
|
|
26
|
-
confirmed: 1,
|
|
27
|
-
finalized: 2,
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
interface TransactionConfirmationRequest {
|
|
31
|
-
txSig: string;
|
|
32
|
-
desiredConfirmationStatus: TransactionConfirmationStatus;
|
|
33
|
-
timeout: number;
|
|
34
|
-
pollInterval: number;
|
|
35
|
-
searchTransactionHistory: boolean;
|
|
36
|
-
startTime: number;
|
|
37
|
-
resolve: (status: SignatureStatus) => void;
|
|
38
|
-
reject: (error: Error) => void;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Class to await for transaction confirmations in an optimised manner. It tracks a shared list of all pending transactions and fetches them in bulk in a shared RPC request whenever they have an "overlapping" polling interval. E.g. tx1 with an interval of 200ms and tx2 with an interval of 300ms (if sent at the same time) will be fetched together at 600ms, 1200ms, 1800ms, etc.
|
|
43
|
-
*/
|
|
44
|
-
export class TransactionConfirmationManager {
|
|
45
|
-
private connection: Connection;
|
|
46
|
-
private pendingConfirmations: Map<string, TransactionConfirmationRequest> =
|
|
47
|
-
new Map();
|
|
48
|
-
private intervalId: ReturnType<typeof setTimeout> | null = null;
|
|
49
|
-
|
|
50
|
-
constructor(connection: Connection) {
|
|
51
|
-
this.connection = connection;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Waits for a transaction to reach `desiredConfirmationStatus` using a `connection.onSignature`
|
|
56
|
-
* websocket subscription, racing it against a one-shot `getSignatureStatuses` check (in case
|
|
57
|
-
* the transaction already confirmed before the subscription was established) and a timeout.
|
|
58
|
-
* The websocket listener is always removed before returning/throwing.
|
|
59
|
-
* @param txSig - Transaction signature to confirm.
|
|
60
|
-
* @param timeout - Milliseconds to wait before giving up; defaults to 30000 (30s).
|
|
61
|
-
* @param desiredConfirmationStatus - Confirmation level to wait for (`'processed'` <
|
|
62
|
-
* `'confirmed'` < `'finalized'`); defaults to `DEFAULT_CONFIRMATION_OPTS.commitment` (`'confirmed'`).
|
|
63
|
-
* @returns The RPC response once `txSig` reaches (or exceeds) `desiredConfirmationStatus`.
|
|
64
|
-
* @throws Error via `throwTransactionError` if the one-shot status check finds the transaction
|
|
65
|
-
* already failed on-chain; `TxSendError` (code `NOT_CONFIRMED_ERROR_CODE`) if neither the
|
|
66
|
-
* one-shot check nor the websocket confirms it within `timeout` — in that case the transaction's
|
|
67
|
-
* actual outcome is unknown, not necessarily failed.
|
|
68
|
-
*/
|
|
69
|
-
async confirmTransactionWebSocket(
|
|
70
|
-
txSig: string,
|
|
71
|
-
timeout = 30000,
|
|
72
|
-
desiredConfirmationStatus = DEFAULT_CONFIRMATION_OPTS.commitment as TransactionConfirmationStatus
|
|
73
|
-
): Promise<RpcResponseAndContext<SignatureResult>> {
|
|
74
|
-
const start = Date.now();
|
|
75
|
-
const subscriptionCommitment =
|
|
76
|
-
desiredConfirmationStatus || DEFAULT_CONFIRMATION_OPTS.commitment;
|
|
77
|
-
|
|
78
|
-
let response: RpcResponseAndContext<SignatureResult> | null = null;
|
|
79
|
-
|
|
80
|
-
let subscriptionId: ClientSubscriptionId | undefined;
|
|
81
|
-
|
|
82
|
-
const confirmationPromise = new Promise((resolve, reject) => {
|
|
83
|
-
try {
|
|
84
|
-
subscriptionId = this.connection.onSignature(
|
|
85
|
-
txSig,
|
|
86
|
-
(result: SignatureResult, context: Context) => {
|
|
87
|
-
response = {
|
|
88
|
-
context,
|
|
89
|
-
value: result,
|
|
90
|
-
};
|
|
91
|
-
resolve(null);
|
|
92
|
-
},
|
|
93
|
-
subscriptionCommitment
|
|
94
|
-
);
|
|
95
|
-
} catch (err) {
|
|
96
|
-
reject(err);
|
|
97
|
-
}
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
// We do a one-shot confirmation check just in case the transaction is ALREADY confirmed when we create the websocket confirmation .. We want to run this concurrently with the onSignature subscription. If this returns true then we can return early as the transaction has already been confirmed.
|
|
101
|
-
const oneShotConfirmationPromise = this.connection.getSignatureStatuses([
|
|
102
|
-
txSig,
|
|
103
|
-
]);
|
|
104
|
-
|
|
105
|
-
const resolveReference: ResolveReference = {};
|
|
106
|
-
|
|
107
|
-
// This is the promise we are waiting on to resolve the overall confirmation. It will resolve the faster of a positive oneShot confirmation, or the websocket confirmation, or the timeout.
|
|
108
|
-
const overallWaitingForConfirmationPromise = new Promise<void>(
|
|
109
|
-
(resolve) => {
|
|
110
|
-
resolveReference.resolve = resolve;
|
|
111
|
-
}
|
|
112
|
-
);
|
|
113
|
-
|
|
114
|
-
// Await for the one shot confirmation and resolve the waiting promise if we get a positive confirmation result
|
|
115
|
-
oneShotConfirmationPromise.then(
|
|
116
|
-
async (oneShotResponse) => {
|
|
117
|
-
if (!oneShotResponse || !oneShotResponse?.value?.[0]) return;
|
|
118
|
-
|
|
119
|
-
const resultValue = oneShotResponse.value[0];
|
|
120
|
-
|
|
121
|
-
if (resultValue.err) {
|
|
122
|
-
await throwTransactionError(txSig, this.connection);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
if (
|
|
126
|
-
this.checkStatusMatchesDesiredConfirmationStatus(
|
|
127
|
-
resultValue,
|
|
128
|
-
desiredConfirmationStatus
|
|
129
|
-
)
|
|
130
|
-
) {
|
|
131
|
-
response = {
|
|
132
|
-
context: oneShotResponse.context,
|
|
133
|
-
value: oneShotResponse.value[0],
|
|
134
|
-
};
|
|
135
|
-
resolveReference.resolve?.();
|
|
136
|
-
}
|
|
137
|
-
},
|
|
138
|
-
(onRejected) => {
|
|
139
|
-
throw onRejected;
|
|
140
|
-
}
|
|
141
|
-
);
|
|
142
|
-
|
|
143
|
-
// Await for the websocket confirmation with the configured timeout
|
|
144
|
-
promiseTimeout(confirmationPromise, timeout).then(
|
|
145
|
-
() => {
|
|
146
|
-
resolveReference.resolve?.();
|
|
147
|
-
},
|
|
148
|
-
(onRejected) => {
|
|
149
|
-
throw onRejected;
|
|
150
|
-
}
|
|
151
|
-
);
|
|
152
|
-
|
|
153
|
-
try {
|
|
154
|
-
await overallWaitingForConfirmationPromise;
|
|
155
|
-
} finally {
|
|
156
|
-
if (subscriptionId !== undefined) {
|
|
157
|
-
this.connection.removeSignatureListener(subscriptionId);
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
const duration = (Date.now() - start) / 1000;
|
|
162
|
-
|
|
163
|
-
if (response === null) {
|
|
164
|
-
throw new TxSendError(
|
|
165
|
-
`Transaction was not confirmed in ${duration.toFixed(
|
|
166
|
-
2
|
|
167
|
-
)} seconds. It is unknown if it succeeded or failed. Check signature ${txSig} using the Solana Explorer or CLI tools.`,
|
|
168
|
-
NOT_CONFIRMED_ERROR_CODE
|
|
169
|
-
);
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
return response;
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
/**
|
|
176
|
-
* Waits for a transaction to reach `desiredConfirmationStatus` by polling
|
|
177
|
-
* `getSignatureStatuses` on a shared 100ms tick (see class doc) rather than a
|
|
178
|
-
* per-transaction interval — this call registers `txSig` and starts the shared loop if it
|
|
179
|
-
* isn't already running.
|
|
180
|
-
* @param txSig - Transaction signature to confirm.
|
|
181
|
-
* @param desiredConfirmationStatus - Confirmation level to wait for; defaults to
|
|
182
|
-
* `DEFAULT_CONFIRMATION_OPTS.commitment` (`'confirmed'`).
|
|
183
|
-
* @param timeout - Milliseconds to wait before rejecting; defaults to 30000 (30s).
|
|
184
|
-
* @param pollInterval - How often (ms) to actually check this transaction's status against the
|
|
185
|
-
* shared 100ms tick; must be at least 400 and a multiple of 100. Defaults to 1000 (1s).
|
|
186
|
-
* @param searchTransactionHistory - Whether to also search already-purged ledger history for
|
|
187
|
-
* this signature (passed to `getSignatureStatuses`); defaults to `false`. If any transaction
|
|
188
|
-
* batched into the same poll round requests this, the whole batch's RPC call requests it.
|
|
189
|
-
* @returns The `SignatureStatus` once `txSig` reaches (or exceeds) `desiredConfirmationStatus`.
|
|
190
|
-
* @throws Error if `pollInterval` is invalid, if the poll times out, or if the transaction is
|
|
191
|
-
* found to have failed on-chain (rejected with the resolved transaction error).
|
|
192
|
-
*/
|
|
193
|
-
async confirmTransactionPolling(
|
|
194
|
-
txSig: string,
|
|
195
|
-
desiredConfirmationStatus = DEFAULT_CONFIRMATION_OPTS.commitment as TransactionConfirmationStatus,
|
|
196
|
-
timeout = 30000,
|
|
197
|
-
pollInterval = 1000,
|
|
198
|
-
searchTransactionHistory = false
|
|
199
|
-
): Promise<SignatureStatus> {
|
|
200
|
-
// Interval must be > 400ms and a multiple of 100ms
|
|
201
|
-
if (pollInterval < 400 || pollInterval % 100 !== 0) {
|
|
202
|
-
throw new Error(
|
|
203
|
-
'Transaction confirmation polling interval must be at least 400ms and a multiple of 100ms'
|
|
204
|
-
);
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
return new Promise((resolve, reject) => {
|
|
208
|
-
this.pendingConfirmations.set(txSig, {
|
|
209
|
-
txSig,
|
|
210
|
-
desiredConfirmationStatus,
|
|
211
|
-
timeout,
|
|
212
|
-
pollInterval,
|
|
213
|
-
searchTransactionHistory,
|
|
214
|
-
startTime: Date.now(),
|
|
215
|
-
resolve,
|
|
216
|
-
reject,
|
|
217
|
-
});
|
|
218
|
-
|
|
219
|
-
if (!this.intervalId) {
|
|
220
|
-
this.startConfirmationLoop();
|
|
221
|
-
}
|
|
222
|
-
});
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
private startConfirmationLoop() {
|
|
226
|
-
this.intervalId = setInterval(() => this.checkPendingConfirmations(), 100);
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
private async checkPendingConfirmations() {
|
|
230
|
-
const now = Date.now();
|
|
231
|
-
const transactionsToCheck: TransactionConfirmationRequest[] = [];
|
|
232
|
-
|
|
233
|
-
for (const [txSig, request] of this.pendingConfirmations.entries()) {
|
|
234
|
-
if (now - request.startTime >= request.timeout) {
|
|
235
|
-
request.reject(
|
|
236
|
-
new Error(
|
|
237
|
-
`Transaction confirmation timeout after ${request.timeout}ms`
|
|
238
|
-
)
|
|
239
|
-
);
|
|
240
|
-
this.pendingConfirmations.delete(txSig);
|
|
241
|
-
} else if ((now - request.startTime) % request.pollInterval < 100) {
|
|
242
|
-
transactionsToCheck.push(request);
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
if (transactionsToCheck.length > 0) {
|
|
247
|
-
await this.checkTransactionStatuses(transactionsToCheck);
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
if (this.pendingConfirmations.size === 0 && this.intervalId) {
|
|
251
|
-
clearInterval(this.intervalId);
|
|
252
|
-
this.intervalId = null;
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
private checkStatusMatchesDesiredConfirmationStatus(
|
|
257
|
-
status: SignatureStatus,
|
|
258
|
-
desiredConfirmationStatus: TransactionConfirmationStatus
|
|
259
|
-
): boolean {
|
|
260
|
-
if (
|
|
261
|
-
status.confirmationStatus &&
|
|
262
|
-
confirmationStatusValues[status.confirmationStatus] >=
|
|
263
|
-
confirmationStatusValues[desiredConfirmationStatus]
|
|
264
|
-
) {
|
|
265
|
-
return true;
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
return false;
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
private async checkTransactionStatuses(
|
|
272
|
-
requests: TransactionConfirmationRequest[]
|
|
273
|
-
) {
|
|
274
|
-
const txSigs = requests.map((request) => request.txSig);
|
|
275
|
-
const { value: statuses } = await this.connection.getSignatureStatuses(
|
|
276
|
-
txSigs,
|
|
277
|
-
{
|
|
278
|
-
searchTransactionHistory: requests.some(
|
|
279
|
-
(req) => req.searchTransactionHistory
|
|
280
|
-
),
|
|
281
|
-
}
|
|
282
|
-
);
|
|
283
|
-
|
|
284
|
-
if (!statuses || statuses.length !== txSigs.length) {
|
|
285
|
-
throw new Error('Failed to get signature statuses');
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
for (let i = 0; i < statuses.length; i++) {
|
|
289
|
-
const status = statuses[i];
|
|
290
|
-
const request = requests[i];
|
|
291
|
-
|
|
292
|
-
if (status === null) {
|
|
293
|
-
continue;
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
if (status.err) {
|
|
297
|
-
this.pendingConfirmations.delete(request.txSig);
|
|
298
|
-
const txError = await getTransactionErrorFromTxSig(
|
|
299
|
-
request.txSig,
|
|
300
|
-
this.connection
|
|
301
|
-
);
|
|
302
|
-
request.reject(
|
|
303
|
-
txError ??
|
|
304
|
-
new Error(
|
|
305
|
-
`Transaction failed but no error could be resolved for signature ${request.txSig}`
|
|
306
|
-
)
|
|
307
|
-
);
|
|
308
|
-
continue;
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
if (
|
|
312
|
-
status.confirmationStatus === undefined ||
|
|
313
|
-
confirmationStatusValues[status.confirmationStatus] === undefined ||
|
|
314
|
-
confirmationStatusValues[request.desiredConfirmationStatus] ===
|
|
315
|
-
undefined
|
|
316
|
-
) {
|
|
317
|
-
throw new Error(
|
|
318
|
-
`Invalid confirmation status when awaiting confirmation: ${status.confirmationStatus}`
|
|
319
|
-
);
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
if (
|
|
323
|
-
this.checkStatusMatchesDesiredConfirmationStatus(
|
|
324
|
-
status,
|
|
325
|
-
request.desiredConfirmationStatus
|
|
326
|
-
)
|
|
327
|
-
) {
|
|
328
|
-
request.resolve(status);
|
|
329
|
-
this.pendingConfirmations.delete(request.txSig);
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
}
|
package/src/util/chainClock.ts
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import { Commitment } from '@solana/web3.js';
|
|
2
|
-
|
|
3
|
-
/** Last-known chain progress at a given commitment level: block height, slot, and unix timestamp (seconds). Any field may be absent if never observed. */
|
|
4
|
-
export type ChainClockProgress = {
|
|
5
|
-
blockHeight?: number;
|
|
6
|
-
slot?: number;
|
|
7
|
-
ts?: number;
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
/** A `ChainClockProgress` update tagged with the commitment level it was observed at. */
|
|
11
|
-
export type ChainClockUpdateProps = {
|
|
12
|
-
commitment: Commitment;
|
|
13
|
-
} & ChainClockProgress;
|
|
14
|
-
|
|
15
|
-
/** Internal state map: one `ChainClockProgress` per `Commitment` level. */
|
|
16
|
-
export type ChainClockState = Map<Commitment, ChainClockProgress>;
|
|
17
|
-
|
|
18
|
-
/** Initial per-commitment progress values to seed a `ChainClock` with. */
|
|
19
|
-
export type ChainClickInitialisationProps = ChainClockUpdateProps[];
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Tracks the most recently observed block height/slot/timestamp per commitment level, so callers
|
|
23
|
-
* (e.g. tx senders deciding whether a blockhash has expired) can read the latest known chain
|
|
24
|
-
* progress without an RPC round-trip.
|
|
25
|
-
*/
|
|
26
|
-
export class ChainClock {
|
|
27
|
-
private _state: ChainClockState;
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* @param props - Initial progress values, one entry per commitment level to track.
|
|
31
|
-
*/
|
|
32
|
-
constructor(props: ChainClickInitialisationProps) {
|
|
33
|
-
this._state = new Map<Commitment, ChainClockUpdateProps>();
|
|
34
|
-
props.forEach((prop) => {
|
|
35
|
-
this._state.set(prop.commitment, prop);
|
|
36
|
-
});
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Merges a new observation into the tracked state for `props.commitment`. Only fields present
|
|
41
|
-
* on `props` are updated (falsy/omitted `blockHeight`/`slot`/`ts` leave the existing stored
|
|
42
|
-
* value untouched, including `0` being treated as absent); the commitment level is created if
|
|
43
|
-
* not already tracked.
|
|
44
|
-
* @param props - New progress observation, tagged with its commitment level.
|
|
45
|
-
*/
|
|
46
|
-
update(props: ChainClockUpdateProps): void {
|
|
47
|
-
const state = this._state.get(props.commitment);
|
|
48
|
-
if (state) {
|
|
49
|
-
if (props.blockHeight) state.blockHeight = props.blockHeight;
|
|
50
|
-
if (props.slot) state.slot = props.slot;
|
|
51
|
-
if (props.ts) state.ts = props.ts;
|
|
52
|
-
} else {
|
|
53
|
-
this._state.set(props.commitment, props);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Reads the last-known progress at a commitment level.
|
|
59
|
-
* @param commitment - Commitment level to read.
|
|
60
|
-
* @returns The tracked `ChainClockProgress`, or `undefined` if nothing has been observed yet at that level.
|
|
61
|
-
*/
|
|
62
|
-
public getState(commitment: Commitment): ChainClockProgress | undefined {
|
|
63
|
-
return this._state.get(commitment);
|
|
64
|
-
}
|
|
65
|
-
}
|
package/src/util/computeUnits.ts
DELETED
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
ComputeBudgetProgram,
|
|
3
|
-
Connection,
|
|
4
|
-
Finality,
|
|
5
|
-
PublicKey,
|
|
6
|
-
TransactionInstruction,
|
|
7
|
-
} from '@solana/web3.js';
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Fetches a confirmed transaction and extracts, from its log messages, every "consumed compute
|
|
11
|
-
* units" line attributable to `programId`. A transaction can invoke the same program more than
|
|
12
|
-
* once (e.g. via CPI or multiple instructions), so this returns one entry per matching log line
|
|
13
|
-
* rather than a single total.
|
|
14
|
-
* @param programId - Program whose compute-unit consumption to extract.
|
|
15
|
-
* @param connection - RPC connection used to fetch the transaction.
|
|
16
|
-
* @param txSignature - Signature of the transaction to inspect.
|
|
17
|
-
* @param commitment - Finality level to fetch the transaction at; defaults to `'confirmed'`.
|
|
18
|
-
* @returns The consumed-compute-unit counts (as strings, parsed straight from the log text) for
|
|
19
|
-
* each invocation of `programId` found in the transaction's logs; empty if the transaction has no
|
|
20
|
-
* log messages (e.g. not yet available at the requested commitment).
|
|
21
|
-
*/
|
|
22
|
-
export async function findComputeUnitConsumption(
|
|
23
|
-
programId: PublicKey,
|
|
24
|
-
connection: Connection,
|
|
25
|
-
txSignature: string,
|
|
26
|
-
commitment: Finality = 'confirmed'
|
|
27
|
-
): Promise<string[]> {
|
|
28
|
-
const tx = await connection.getTransaction(txSignature, { commitment });
|
|
29
|
-
const computeUnits: string[] = [];
|
|
30
|
-
const logMessages = tx?.meta?.logMessages;
|
|
31
|
-
if (!logMessages) {
|
|
32
|
-
return computeUnits;
|
|
33
|
-
}
|
|
34
|
-
const regex = new RegExp(
|
|
35
|
-
`Program ${programId.toString()} consumed ([0-9]{0,6}) of ([0-9]{0,7}) compute units`
|
|
36
|
-
);
|
|
37
|
-
logMessages.forEach((logMessage) => {
|
|
38
|
-
const match = logMessage.match(regex);
|
|
39
|
-
if (match && match[1]) {
|
|
40
|
-
computeUnits.push(match[1]);
|
|
41
|
-
}
|
|
42
|
-
});
|
|
43
|
-
return computeUnits;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Checks whether `ix` is a `ComputeBudgetProgram.setComputeUnitLimit` instruction, by matching
|
|
48
|
-
* the program id and the instruction discriminator byte (`2`).
|
|
49
|
-
* @param ix - Instruction to check.
|
|
50
|
-
* @returns `true` if `ix` sets the transaction's compute unit limit.
|
|
51
|
-
*/
|
|
52
|
-
export function isSetComputeUnitsIx(ix: TransactionInstruction): boolean {
|
|
53
|
-
// Compute budget program discriminator is first byte
|
|
54
|
-
// 2: set compute unit limit
|
|
55
|
-
// 3: set compute unit price
|
|
56
|
-
if (
|
|
57
|
-
ix.programId.equals(ComputeBudgetProgram.programId) &&
|
|
58
|
-
// @ts-ignore
|
|
59
|
-
ix.data.at(0) === 2
|
|
60
|
-
) {
|
|
61
|
-
return true;
|
|
62
|
-
}
|
|
63
|
-
return false;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Checks whether `ix` is a `ComputeBudgetProgram.setComputeUnitPrice` instruction, by matching
|
|
68
|
-
* the program id and the instruction discriminator byte (`3`).
|
|
69
|
-
* @param ix - Instruction to check.
|
|
70
|
-
* @returns `true` if `ix` sets the transaction's compute unit price (priority fee).
|
|
71
|
-
*/
|
|
72
|
-
export function isSetComputeUnitPriceIx(ix: TransactionInstruction): boolean {
|
|
73
|
-
// Compute budget program discriminator is first byte
|
|
74
|
-
// 2: set compute unit limit
|
|
75
|
-
// 3: set compute unit price
|
|
76
|
-
if (
|
|
77
|
-
ix.programId.equals(ComputeBudgetProgram.programId) &&
|
|
78
|
-
// @ts-ignore
|
|
79
|
-
ix.data.at(0) === 3
|
|
80
|
-
) {
|
|
81
|
-
return true;
|
|
82
|
-
}
|
|
83
|
-
return false;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Checks a list of instructions for the presence of compute-budget limit/price instructions —
|
|
88
|
-
* used by tx builders to avoid appending a duplicate `setComputeUnitLimit`/`setComputeUnitPrice`
|
|
89
|
-
* instruction when the caller already supplied one.
|
|
90
|
-
* @param ixs - Instructions to scan (typically an in-progress transaction's instruction list).
|
|
91
|
-
* @returns Whether a `setComputeUnitLimit` and/or `setComputeUnitPrice` instruction is present.
|
|
92
|
-
*/
|
|
93
|
-
export function containsComputeUnitIxs(ixs: TransactionInstruction[]): {
|
|
94
|
-
hasSetComputeUnitLimitIx: boolean;
|
|
95
|
-
hasSetComputeUnitPriceIx: boolean;
|
|
96
|
-
} {
|
|
97
|
-
return {
|
|
98
|
-
hasSetComputeUnitLimitIx: ixs.some(isSetComputeUnitsIx),
|
|
99
|
-
hasSetComputeUnitPriceIx: ixs.some(isSetComputeUnitPriceIx),
|
|
100
|
-
};
|
|
101
|
-
}
|
package/src/util/digest.ts
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { createHash } from 'crypto';
|
|
2
|
-
import { nanoid } from 'nanoid';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Computes the raw SHA-256 digest of arbitrary data.
|
|
6
|
-
* @param data - Bytes to hash.
|
|
7
|
-
* @returns The 32-byte SHA-256 digest.
|
|
8
|
-
*/
|
|
9
|
-
export function digest(data: Buffer): Buffer {
|
|
10
|
-
const hash = createHash('sha256');
|
|
11
|
-
hash.update(data);
|
|
12
|
-
return hash.digest();
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Computes a base64-encoded SHA-256 digest of a signature, used as a compact, collision-resistant
|
|
17
|
-
* dedup/lookup key for signed messages (e.g. swift/signed-message orders) without storing the full
|
|
18
|
-
* signature.
|
|
19
|
-
* @param signature - Raw signature bytes to hash.
|
|
20
|
-
* @returns The base64-encoded SHA-256 digest.
|
|
21
|
-
*/
|
|
22
|
-
export function digestSignature(signature: Uint8Array): string {
|
|
23
|
-
return createHash('sha256').update(signature).digest('base64');
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Generates a random 8-character uuid for tagging a signed-message (swift) order, matching the
|
|
28
|
-
* `uuid: Uint8Array` field expected on-chain/by the swift server.
|
|
29
|
-
* @returns 8 raw bytes (the ASCII/UTF-8 encoding of an 8-character nanoid string).
|
|
30
|
-
*/
|
|
31
|
-
export function generateSignedMsgUuid(): Uint8Array {
|
|
32
|
-
return Uint8Array.from(Buffer.from(nanoid(8)));
|
|
33
|
-
}
|
package/src/util/ed25519Utils.ts
DELETED
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
import { Ed25519Program, TransactionInstruction } from '@solana/web3.js';
|
|
2
|
-
import * as BufferLayout from '@solana/buffer-layout';
|
|
3
|
-
|
|
4
|
-
const ED25519_INSTRUCTION_LEN = 16;
|
|
5
|
-
const SIGNATURE_LEN = 64;
|
|
6
|
-
const PUBKEY_LEN = 32;
|
|
7
|
-
const MAGIC_LEN = 4;
|
|
8
|
-
const MESSAGE_SIZE_LEN = 2;
|
|
9
|
-
|
|
10
|
-
const readUint16LE = (data: Uint8Array, offset: number) => {
|
|
11
|
-
return data[offset] | (data[offset + 1] << 8);
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
const ED25519_INSTRUCTION_LAYOUT = BufferLayout.struct<
|
|
15
|
-
Readonly<{
|
|
16
|
-
messageDataOffset: number;
|
|
17
|
-
messageDataSize: number;
|
|
18
|
-
messageInstructionIndex: number;
|
|
19
|
-
numSignatures: number;
|
|
20
|
-
padding: number;
|
|
21
|
-
publicKeyInstructionIndex: number;
|
|
22
|
-
publicKeyOffset: number;
|
|
23
|
-
signatureInstructionIndex: number;
|
|
24
|
-
signatureOffset: number;
|
|
25
|
-
}>
|
|
26
|
-
>([
|
|
27
|
-
BufferLayout.u8('numSignatures'),
|
|
28
|
-
BufferLayout.u8('padding'),
|
|
29
|
-
BufferLayout.u16('signatureOffset'),
|
|
30
|
-
BufferLayout.u16('signatureInstructionIndex'),
|
|
31
|
-
BufferLayout.u16('publicKeyOffset'),
|
|
32
|
-
BufferLayout.u16('publicKeyInstructionIndex'),
|
|
33
|
-
BufferLayout.u16('messageDataOffset'),
|
|
34
|
-
BufferLayout.u16('messageDataSize'),
|
|
35
|
-
BufferLayout.u16('messageInstructionIndex'),
|
|
36
|
-
]);
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Constructs a minimal Ed25519 verification instruction that, instead of embedding its own copy
|
|
40
|
-
* of the signature/pubkey/message, points its offsets at data already present inside another
|
|
41
|
-
* instruction in the same transaction (e.g. `postPythLazerOracleUpdate`, `placeSignedMsgTakerOrder`).
|
|
42
|
-
* This lets the native ed25519 program verify a signature the velocity program also needs to read,
|
|
43
|
-
* without duplicating the signed payload in the transaction (which would blow the size limit for
|
|
44
|
-
* larger payloads like Lazer updates). The Solana runtime requires this ed25519 verify instruction
|
|
45
|
-
* to be a sibling instruction (not a CPI) executed before the instruction that relies on it.
|
|
46
|
-
*
|
|
47
|
-
* @param customInstructionIndex The index of the custom instruction in the transaction (e.g. if tx contains compute budget limit, compute budget price, ed25519 verify, custom ix, this would be 3).
|
|
48
|
-
* @param messageOffset The offset within the custom instruction data where the signed message begins.
|
|
49
|
-
* @param customInstructionData The entire instruction data array for the custom instruction.
|
|
50
|
-
* @param magicLen Length, in bytes, of a "magic"/tag prefix between `messageOffset` and the
|
|
51
|
-
* start of the 64-byte signature; defaults to `MAGIC_LEN` (4) if omitted.
|
|
52
|
-
* @returns A `TransactionInstruction` targeting `Ed25519Program` with no accounts, whose data
|
|
53
|
-
* encodes offsets (not copies) of the signature/pubkey/message living inside the referenced
|
|
54
|
-
* custom instruction.
|
|
55
|
-
*/
|
|
56
|
-
export function createMinimalEd25519VerifyIx(
|
|
57
|
-
customInstructionIndex: number,
|
|
58
|
-
messageOffset: number,
|
|
59
|
-
customInstructionData: Uint8Array,
|
|
60
|
-
magicLen?: number
|
|
61
|
-
): TransactionInstruction {
|
|
62
|
-
const signatureOffset =
|
|
63
|
-
messageOffset + (magicLen === undefined ? MAGIC_LEN : magicLen);
|
|
64
|
-
const publicKeyOffset = signatureOffset + SIGNATURE_LEN;
|
|
65
|
-
const messageDataSizeOffset = publicKeyOffset + PUBKEY_LEN;
|
|
66
|
-
const messageDataOffset = messageDataSizeOffset + MESSAGE_SIZE_LEN;
|
|
67
|
-
|
|
68
|
-
const messageDataSize = readUint16LE(
|
|
69
|
-
customInstructionData,
|
|
70
|
-
messageDataSizeOffset - messageOffset
|
|
71
|
-
);
|
|
72
|
-
|
|
73
|
-
const instructionData = Buffer.alloc(ED25519_INSTRUCTION_LEN);
|
|
74
|
-
|
|
75
|
-
ED25519_INSTRUCTION_LAYOUT.encode(
|
|
76
|
-
{
|
|
77
|
-
numSignatures: 1,
|
|
78
|
-
padding: 0,
|
|
79
|
-
signatureOffset,
|
|
80
|
-
signatureInstructionIndex: customInstructionIndex,
|
|
81
|
-
publicKeyOffset,
|
|
82
|
-
publicKeyInstructionIndex: customInstructionIndex,
|
|
83
|
-
messageDataOffset,
|
|
84
|
-
messageDataSize: messageDataSize,
|
|
85
|
-
messageInstructionIndex: customInstructionIndex,
|
|
86
|
-
},
|
|
87
|
-
instructionData
|
|
88
|
-
);
|
|
89
|
-
|
|
90
|
-
return new TransactionInstruction({
|
|
91
|
-
keys: [],
|
|
92
|
-
programId: Ed25519Program.programId,
|
|
93
|
-
data: instructionData,
|
|
94
|
-
});
|
|
95
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Races `promise` against a timer, resolving to `null` instead of rejecting/hanging if `promise`
|
|
3
|
-
* doesn't settle within `timeoutMs`. `promise` itself is not cancelled — it keeps running in the
|
|
4
|
-
* background and its eventual result/rejection is discarded once the race is decided.
|
|
5
|
-
* @param promise - The promise to await.
|
|
6
|
-
* @param timeoutMs - Timeout in milliseconds.
|
|
7
|
-
* @returns `promise`'s resolved value, or `null` if it didn't settle before `timeoutMs` elapsed.
|
|
8
|
-
* Rejects if `promise` rejects before the timeout.
|
|
9
|
-
*/
|
|
10
|
-
export function promiseTimeout<T>(
|
|
11
|
-
promise: Promise<T>,
|
|
12
|
-
timeoutMs: number
|
|
13
|
-
): Promise<T | null> {
|
|
14
|
-
let timeoutId: ReturnType<typeof setTimeout>;
|
|
15
|
-
const timeoutPromise: Promise<null> = new Promise((resolve) => {
|
|
16
|
-
timeoutId = setTimeout(() => resolve(null), timeoutMs);
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
return Promise.race([promise, timeoutPromise]).then((result: T | null) => {
|
|
20
|
-
clearTimeout(timeoutId);
|
|
21
|
-
return result;
|
|
22
|
-
});
|
|
23
|
-
}
|