@sip-protocol/sdk 0.7.3 → 0.7.4
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/LICENSE +21 -0
- package/README.md +267 -0
- package/dist/{TransportWebUSB-TQ7WZ4LE.mjs → TransportWebUSB-YQMAGJAJ.mjs} +12 -9
- package/dist/browser.d.mts +10 -4
- package/dist/browser.d.ts +10 -4
- package/dist/browser.js +47556 -19603
- package/dist/browser.mjs +628 -48
- package/dist/chunk-4GRJ5MAW.mjs +152 -0
- package/dist/chunk-5D7A3L3W.mjs +717 -0
- package/dist/chunk-64AYA5F5.mjs +7834 -0
- package/dist/chunk-GMDGB22A.mjs +379 -0
- package/dist/chunk-I534WKN7.mjs +328 -0
- package/dist/chunk-IBZVA5Y7.mjs +1003 -0
- package/dist/chunk-PRRZAWJE.mjs +223 -0
- package/dist/{chunk-UJCSKKID.mjs → chunk-XGB3TDIC.mjs} +13 -1
- package/dist/{chunk-3M3HNQCW.mjs → chunk-YWGJ77A2.mjs} +28656 -13103
- package/dist/{chunk-6WGN57S2.mjs → chunk-Z3K7W5S3.mjs} +48 -0
- package/dist/constants-LHAAUC2T.mjs +51 -0
- package/dist/dist-2OGQ7FED.mjs +3957 -0
- package/dist/dist-IFHPYLDX.mjs +254 -0
- package/dist/fulfillment_proof-ANHVPKTB.mjs +21 -0
- package/dist/funding_proof-ICFZ5LHY.mjs +21 -0
- package/dist/{index-DIBZHOOQ.d.ts → index-DXh2IGkz.d.ts} +21239 -10304
- package/dist/{index-8MQz13eJ.d.mts → index-DeE1ZzA4.d.mts} +21239 -10304
- package/dist/index.d.mts +9 -3
- package/dist/index.d.ts +9 -3
- package/dist/index.js +48396 -19623
- package/dist/index.mjs +537 -19
- package/dist/interface-Bf7w1PLW.d.mts +679 -0
- package/dist/interface-Bf7w1PLW.d.ts +679 -0
- package/dist/{noir-DKfEzWy9.d.mts → noir-kzbLVTei.d.mts} +31 -21
- package/dist/{noir-DKfEzWy9.d.ts → noir-kzbLVTei.d.ts} +31 -21
- package/dist/proofs/halo2.d.mts +151 -0
- package/dist/proofs/halo2.d.ts +151 -0
- package/dist/proofs/halo2.js +350 -0
- package/dist/proofs/halo2.mjs +11 -0
- package/dist/proofs/kimchi.d.mts +160 -0
- package/dist/proofs/kimchi.d.ts +160 -0
- package/dist/proofs/kimchi.js +431 -0
- package/dist/proofs/kimchi.mjs +13 -0
- package/dist/proofs/noir.d.mts +1 -1
- package/dist/proofs/noir.d.ts +1 -1
- package/dist/proofs/noir.js +74 -18
- package/dist/proofs/noir.mjs +84 -24
- package/dist/solana-U3MEGU7W.mjs +280 -0
- package/dist/validity_proof-3POXLPNY.mjs +21 -0
- package/package.json +54 -21
- package/src/adapters/index.ts +41 -0
- package/src/adapters/jupiter.ts +571 -0
- package/src/adapters/near-intents.ts +135 -0
- package/src/advisor/advisor.ts +653 -0
- package/src/advisor/index.ts +54 -0
- package/src/advisor/tools.ts +303 -0
- package/src/advisor/types.ts +164 -0
- package/src/chains/ethereum/announcement.ts +536 -0
- package/src/chains/ethereum/bnb-optimizations.ts +474 -0
- package/src/chains/ethereum/commitment.ts +522 -0
- package/src/chains/ethereum/constants.ts +462 -0
- package/src/chains/ethereum/deployment.ts +596 -0
- package/src/chains/ethereum/gas-estimation.ts +538 -0
- package/src/chains/ethereum/index.ts +268 -0
- package/src/chains/ethereum/optimizations.ts +614 -0
- package/src/chains/ethereum/privacy-adapter.ts +855 -0
- package/src/chains/ethereum/registry.ts +584 -0
- package/src/chains/ethereum/rpc.ts +905 -0
- package/src/chains/ethereum/stealth.ts +491 -0
- package/src/chains/ethereum/token.ts +790 -0
- package/src/chains/ethereum/transfer.ts +637 -0
- package/src/chains/ethereum/types.ts +456 -0
- package/src/chains/ethereum/viewing-key.ts +455 -0
- package/src/chains/near/commitment.ts +608 -0
- package/src/chains/near/constants.ts +284 -0
- package/src/chains/near/function-call.ts +871 -0
- package/src/chains/near/history.ts +654 -0
- package/src/chains/near/implicit-account.ts +840 -0
- package/src/chains/near/index.ts +393 -0
- package/src/chains/near/native-transfer.ts +658 -0
- package/src/chains/near/nep141.ts +775 -0
- package/src/chains/near/privacy-adapter.ts +889 -0
- package/src/chains/near/resolver.ts +971 -0
- package/src/chains/near/rpc.ts +1016 -0
- package/src/chains/near/stealth.ts +419 -0
- package/src/chains/near/types.ts +317 -0
- package/src/chains/near/viewing-key.ts +876 -0
- package/src/chains/solana/anchor-transfer.ts +386 -0
- package/src/chains/solana/commitment.ts +577 -0
- package/src/chains/solana/constants.ts +126 -12
- package/src/chains/solana/ephemeral-keys.ts +543 -0
- package/src/chains/solana/index.ts +252 -1
- package/src/chains/solana/key-derivation.ts +418 -0
- package/src/chains/solana/kit-compat.ts +334 -0
- package/src/chains/solana/optimizations.ts +560 -0
- package/src/chains/solana/privacy-adapter.ts +605 -0
- package/src/chains/solana/providers/generic.ts +47 -6
- package/src/chains/solana/providers/helius-enhanced-types.ts +336 -0
- package/src/chains/solana/providers/helius-enhanced.ts +623 -0
- package/src/chains/solana/providers/helius.ts +186 -33
- package/src/chains/solana/providers/index.ts +31 -0
- package/src/chains/solana/providers/interface.ts +61 -18
- package/src/chains/solana/providers/quicknode.ts +409 -0
- package/src/chains/solana/providers/triton.ts +426 -0
- package/src/chains/solana/providers/webhook.ts +338 -67
- package/src/chains/solana/rpc-client.ts +1150 -0
- package/src/chains/solana/scan.ts +83 -66
- package/src/chains/solana/sol-transfer.ts +732 -0
- package/src/chains/solana/spl-transfer.ts +886 -0
- package/src/chains/solana/stealth-scanner.ts +703 -0
- package/src/chains/solana/sunspot-verifier.ts +453 -0
- package/src/chains/solana/transaction-builder.ts +755 -0
- package/src/chains/solana/transfer.ts +74 -5
- package/src/chains/solana/types.ts +57 -6
- package/src/chains/solana/utils.ts +110 -0
- package/src/chains/solana/viewing-key.ts +807 -0
- package/src/compliance/fireblocks.ts +921 -0
- package/src/compliance/index.ts +23 -0
- package/src/compliance/range-sas.ts +398 -33
- package/src/config/endpoints.ts +100 -0
- package/src/crypto.ts +11 -8
- package/src/errors.ts +82 -0
- package/src/evm/erc4337-relayer.ts +830 -0
- package/src/evm/index.ts +47 -0
- package/src/fees/calculator.ts +396 -0
- package/src/fees/index.ts +87 -0
- package/src/fees/near-contract.ts +429 -0
- package/src/fees/types.ts +268 -0
- package/src/index.ts +686 -1
- package/src/intent.ts +6 -3
- package/src/logger.ts +324 -0
- package/src/network/index.ts +80 -0
- package/src/network/proxy.ts +691 -0
- package/src/optimizations/index.ts +541 -0
- package/src/oracle/types.ts +1 -0
- package/src/privacy-backends/arcium-types.ts +727 -0
- package/src/privacy-backends/arcium.ts +719 -0
- package/src/privacy-backends/combined-privacy.ts +866 -0
- package/src/privacy-backends/cspl-token.ts +595 -0
- package/src/privacy-backends/cspl-types.ts +512 -0
- package/src/privacy-backends/cspl.ts +907 -0
- package/src/privacy-backends/health.ts +488 -0
- package/src/privacy-backends/inco-types.ts +323 -0
- package/src/privacy-backends/inco.ts +616 -0
- package/src/privacy-backends/index.ts +254 -4
- package/src/privacy-backends/interface.ts +649 -6
- package/src/privacy-backends/lru-cache.ts +343 -0
- package/src/privacy-backends/magicblock.ts +458 -0
- package/src/privacy-backends/mock.ts +258 -0
- package/src/privacy-backends/privacycash.ts +13 -17
- package/src/privacy-backends/private-swap.ts +570 -0
- package/src/privacy-backends/rate-limiter.ts +683 -0
- package/src/privacy-backends/registry.ts +414 -2
- package/src/privacy-backends/router.ts +283 -3
- package/src/privacy-backends/shadowwire.ts +449 -0
- package/src/privacy-backends/sip-native.ts +3 -0
- package/src/privacy-logger.ts +191 -0
- package/src/production-safety.ts +373 -0
- package/src/proofs/aggregator.ts +1029 -0
- package/src/proofs/browser-composer.ts +1150 -0
- package/src/proofs/browser.ts +113 -25
- package/src/proofs/cache/index.ts +127 -0
- package/src/proofs/cache/interface.ts +545 -0
- package/src/proofs/cache/key-generator.ts +188 -0
- package/src/proofs/cache/lru-cache.ts +481 -0
- package/src/proofs/cache/multi-tier-cache.ts +575 -0
- package/src/proofs/cache/persistent-cache.ts +788 -0
- package/src/proofs/compliance-proof.ts +872 -0
- package/src/proofs/composer/base.ts +923 -0
- package/src/proofs/composer/index.ts +25 -0
- package/src/proofs/composer/interface.ts +518 -0
- package/src/proofs/composer/types.ts +383 -0
- package/src/proofs/converters/halo2.ts +452 -0
- package/src/proofs/converters/index.ts +208 -0
- package/src/proofs/converters/interface.ts +363 -0
- package/src/proofs/converters/kimchi.ts +462 -0
- package/src/proofs/converters/noir.ts +451 -0
- package/src/proofs/fallback.ts +888 -0
- package/src/proofs/halo2.ts +42 -0
- package/src/proofs/index.ts +471 -0
- package/src/proofs/interface.ts +13 -0
- package/src/proofs/kimchi.ts +42 -0
- package/src/proofs/lazy.ts +1004 -0
- package/src/proofs/mock.ts +25 -1
- package/src/proofs/noir.ts +110 -29
- package/src/proofs/orchestrator.ts +960 -0
- package/src/proofs/parallel/concurrency.ts +297 -0
- package/src/proofs/parallel/dependency-graph.ts +602 -0
- package/src/proofs/parallel/executor.ts +420 -0
- package/src/proofs/parallel/index.ts +131 -0
- package/src/proofs/parallel/interface.ts +685 -0
- package/src/proofs/parallel/worker-pool.ts +644 -0
- package/src/proofs/providers/halo2.ts +560 -0
- package/src/proofs/providers/index.ts +34 -0
- package/src/proofs/providers/kimchi.ts +641 -0
- package/src/proofs/validator.ts +881 -0
- package/src/proofs/verifier.ts +867 -0
- package/src/quantum/index.ts +112 -0
- package/src/quantum/winternitz-vault.ts +639 -0
- package/src/quantum/wots.ts +611 -0
- package/src/settlement/backends/direct-chain.ts +1 -0
- package/src/settlement/index.ts +9 -0
- package/src/settlement/router.ts +732 -46
- package/src/solana/index.ts +72 -0
- package/src/solana/jito-relayer.ts +687 -0
- package/src/solana/noir-verifier-types.ts +430 -0
- package/src/solana/noir-verifier.ts +816 -0
- package/src/stealth/address-derivation.ts +193 -0
- package/src/stealth/ed25519.ts +431 -0
- package/src/stealth/index.ts +233 -0
- package/src/stealth/meta-address.ts +221 -0
- package/src/stealth/secp256k1.ts +368 -0
- package/src/stealth/utils.ts +194 -0
- package/src/stealth.ts +50 -1504
- package/src/sync/index.ts +106 -0
- package/src/sync/manager.ts +504 -0
- package/src/sync/mock-provider.ts +318 -0
- package/src/sync/oblivious.ts +625 -0
- package/src/tokens/index.ts +15 -0
- package/src/tokens/registry.ts +301 -0
- package/src/utils/deprecation.ts +94 -0
- package/src/utils/index.ts +9 -0
- package/src/wallet/ethereum/index.ts +68 -0
- package/src/wallet/ethereum/metamask-privacy.ts +420 -0
- package/src/wallet/ethereum/multi-wallet.ts +646 -0
- package/src/wallet/ethereum/privacy-adapter.ts +700 -0
- package/src/wallet/ethereum/types.ts +3 -1
- package/src/wallet/ethereum/walletconnect-adapter.ts +675 -0
- package/src/wallet/hardware/index.ts +10 -0
- package/src/wallet/hardware/ledger-privacy.ts +414 -0
- package/src/wallet/index.ts +71 -0
- package/src/wallet/near/adapter.ts +626 -0
- package/src/wallet/near/index.ts +86 -0
- package/src/wallet/near/meteor-wallet.ts +1153 -0
- package/src/wallet/near/my-near-wallet.ts +790 -0
- package/src/wallet/near/wallet-selector.ts +702 -0
- package/src/wallet/solana/adapter.ts +6 -4
- package/src/wallet/solana/index.ts +13 -0
- package/src/wallet/solana/privacy-adapter.ts +567 -0
- package/src/wallet/sui/types.ts +6 -4
- package/src/zcash/rpc-client.ts +13 -6
- package/dist/chunk-2XIVXWHA.mjs +0 -1930
- package/dist/chunk-3INS3PR5.mjs +0 -884
- package/dist/chunk-3OVABDRH.mjs +0 -17096
- package/dist/chunk-7RFRWDCW.mjs +0 -1504
- package/dist/chunk-DLDWZFYC.mjs +0 -1495
- package/dist/chunk-E6SZWREQ.mjs +0 -57
- package/dist/chunk-F6F73W35.mjs +0 -16166
- package/dist/chunk-G33LB27A.mjs +0 -16166
- package/dist/chunk-HGU6HZRC.mjs +0 -231
- package/dist/chunk-L2K34JCU.mjs +0 -1496
- package/dist/chunk-OFDBEIEK.mjs +0 -16166
- package/dist/chunk-SF7YSLF5.mjs +0 -1515
- package/dist/chunk-SN4ZDTVW.mjs +0 -16166
- package/dist/chunk-WWUSGOXE.mjs +0 -17129
- package/dist/constants-VOI7BSLK.mjs +0 -27
- package/dist/index-B71aXVzk.d.ts +0 -13264
- package/dist/index-BYZbDjal.d.ts +0 -11390
- package/dist/index-CHB3KuOB.d.mts +0 -11859
- package/dist/index-CzWPI6Le.d.ts +0 -11859
- package/dist/index-pOIIuwfV.d.mts +0 -13264
- package/dist/index-xbWjohNq.d.mts +0 -11390
- package/dist/solana-4O4K45VU.mjs +0 -46
- package/dist/solana-5EMCTPTS.mjs +0 -46
- package/dist/solana-NDABAZ6P.mjs +0 -56
- package/dist/solana-Q4NAVBTS.mjs +0 -46
- package/dist/solana-ZYO63LY5.mjs +0 -46
|
@@ -0,0 +1,687 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Jito Relayer for SIP Protocol
|
|
3
|
+
*
|
|
4
|
+
* Enables gas abstraction for Solana shielded transactions using Jito's MEV infrastructure.
|
|
5
|
+
* The relayer submits transaction bundles on behalf of users, paying gas fees and breaking
|
|
6
|
+
* the direct link between the user's wallet and the privacy transaction.
|
|
7
|
+
*
|
|
8
|
+
* ## Why Jito?
|
|
9
|
+
*
|
|
10
|
+
* 1. **Native Solana**: Jito is battle-tested MEV infrastructure on Solana
|
|
11
|
+
* 2. **No Dedicated Server**: Uses Jito's network, no VPS maintenance needed
|
|
12
|
+
* 3. **Bundle Guarantees**: Atomic execution, no partial failures
|
|
13
|
+
* 4. **Lower Regulatory Risk**: Relayer only handles gas, not asset movement
|
|
14
|
+
*
|
|
15
|
+
* ## Architecture
|
|
16
|
+
*
|
|
17
|
+
* ```
|
|
18
|
+
* ┌─────────────────────────────────────────────────────────────────────────────┐
|
|
19
|
+
* │ GAS ABSTRACTION FLOW │
|
|
20
|
+
* │ │
|
|
21
|
+
* │ ┌─────────┐ ┌───────────────┐ ┌───────────┐ ┌──────────┐ │
|
|
22
|
+
* │ │ User │ ──▶ │ Sign TX │ ──▶ │ Jito │ ──▶ │ Solana │ │
|
|
23
|
+
* │ │ Wallet │ │ (no SOL fee) │ │ Relayer │ │ Network │ │
|
|
24
|
+
* │ └─────────┘ └───────────────┘ └───────────┘ └──────────┘ │
|
|
25
|
+
* │ │ │
|
|
26
|
+
* │ ▼ │
|
|
27
|
+
* │ Relayer pays │
|
|
28
|
+
* │ gas from tip │
|
|
29
|
+
* └─────────────────────────────────────────────────────────────────────────────┘
|
|
30
|
+
* ```
|
|
31
|
+
*
|
|
32
|
+
* ## Fee Model
|
|
33
|
+
*
|
|
34
|
+
* The relayer takes a small tip from the transaction (configurable, typically 0.1-0.5%)
|
|
35
|
+
* to cover gas costs and operational overhead.
|
|
36
|
+
*
|
|
37
|
+
* @see https://jito-foundation.gitbook.io/mev/
|
|
38
|
+
* @see https://jito-labs.github.io/jito-ts/
|
|
39
|
+
*/
|
|
40
|
+
|
|
41
|
+
import {
|
|
42
|
+
Connection,
|
|
43
|
+
PublicKey,
|
|
44
|
+
VersionedTransaction,
|
|
45
|
+
Transaction,
|
|
46
|
+
SystemProgram,
|
|
47
|
+
type Keypair,
|
|
48
|
+
type TransactionInstruction,
|
|
49
|
+
} from '@solana/web3.js'
|
|
50
|
+
import { bytesToHex } from '@noble/hashes/utils'
|
|
51
|
+
|
|
52
|
+
// ─── Constants ────────────────────────────────────────────────────────────────
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Jito Block Engine endpoints
|
|
56
|
+
* @see https://jito-foundation.gitbook.io/mev/searcher-resources/block-engine
|
|
57
|
+
*/
|
|
58
|
+
export const JITO_BLOCK_ENGINES = {
|
|
59
|
+
mainnet: {
|
|
60
|
+
amsterdam: 'https://amsterdam.mainnet.block-engine.jito.wtf/api/v1',
|
|
61
|
+
frankfurt: 'https://frankfurt.mainnet.block-engine.jito.wtf/api/v1',
|
|
62
|
+
ny: 'https://ny.mainnet.block-engine.jito.wtf/api/v1',
|
|
63
|
+
tokyo: 'https://tokyo.mainnet.block-engine.jito.wtf/api/v1',
|
|
64
|
+
},
|
|
65
|
+
// Jito doesn't have devnet block engines - use simulation for testing
|
|
66
|
+
} as const
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Jito tip accounts (one must receive the tip)
|
|
70
|
+
* @see https://jito-foundation.gitbook.io/mev/searcher-resources/tip-accounts
|
|
71
|
+
*/
|
|
72
|
+
export const JITO_TIP_ACCOUNTS = [
|
|
73
|
+
'96gYZGLnJYVFmbjzopPSU6QiEV5fGqZNyN9nmNhvrZU5',
|
|
74
|
+
'HFqU5x63VTqvQss8hp11i4bVmkekGTo46ibhvdrPnSVX',
|
|
75
|
+
'Cw8CFyM9FkoMi7K7Crf6HNQqf4uEMzpKw6QNghXLvLkY',
|
|
76
|
+
'ADaUMid9yfUytqMBgopwjb2DTLSokTSzL1zt6iGPaS49',
|
|
77
|
+
'DfXygSm4jCyNCybVYYK6DwvWqjKee8pbDmJGcLWNDXjh',
|
|
78
|
+
'ADuUkR4vqLUMWXxW9gh6D6L8pMSawimctcNZ5pGwDcEt',
|
|
79
|
+
'DttWaMuVvTiduZRnguLF7jNxTgiMBZ1hyAumKUiL2KRL',
|
|
80
|
+
'3AVi9Tg9Uo68tJfuvoKvqKNWKkC5wPdSSdeBnizKZ6jT',
|
|
81
|
+
] as const
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Default configuration values
|
|
85
|
+
*/
|
|
86
|
+
export const JITO_DEFAULTS = {
|
|
87
|
+
/** Default tip in lamports (0.001 SOL) */
|
|
88
|
+
tipLamports: 1_000_000,
|
|
89
|
+
/** Maximum bundle size */
|
|
90
|
+
maxBundleSize: 5,
|
|
91
|
+
/** Bundle submission timeout (ms) */
|
|
92
|
+
submissionTimeout: 30_000,
|
|
93
|
+
/** Confirmation timeout (ms) */
|
|
94
|
+
confirmationTimeout: 60_000,
|
|
95
|
+
/** Default retry attempts */
|
|
96
|
+
maxRetries: 3,
|
|
97
|
+
} as const
|
|
98
|
+
|
|
99
|
+
// ─── Types ────────────────────────────────────────────────────────────────────
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Jito relayer configuration
|
|
103
|
+
*/
|
|
104
|
+
export interface JitoRelayerConfig {
|
|
105
|
+
/** Jito block engine endpoint */
|
|
106
|
+
blockEngineUrl?: string
|
|
107
|
+
/** Solana RPC URL */
|
|
108
|
+
rpcUrl?: string
|
|
109
|
+
/** Default tip amount in lamports */
|
|
110
|
+
defaultTipLamports?: number
|
|
111
|
+
/** Enable debug logging */
|
|
112
|
+
debug?: boolean
|
|
113
|
+
/** Maximum retries for bundle submission */
|
|
114
|
+
maxRetries?: number
|
|
115
|
+
/** Submission timeout in ms */
|
|
116
|
+
submissionTimeout?: number
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Bundle submission request
|
|
121
|
+
*/
|
|
122
|
+
export interface JitoBundleRequest {
|
|
123
|
+
/** Transactions to include in bundle */
|
|
124
|
+
transactions: (Transaction | VersionedTransaction)[]
|
|
125
|
+
/** Tip amount in lamports */
|
|
126
|
+
tipLamports?: number
|
|
127
|
+
/** Tip payer keypair */
|
|
128
|
+
tipPayer: Keypair
|
|
129
|
+
/** Whether to wait for confirmation */
|
|
130
|
+
waitForConfirmation?: boolean
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Bundle submission result
|
|
135
|
+
*/
|
|
136
|
+
export interface JitoBundleResult {
|
|
137
|
+
/** Bundle UUID */
|
|
138
|
+
bundleId: string
|
|
139
|
+
/** Transaction signatures in bundle */
|
|
140
|
+
signatures: string[]
|
|
141
|
+
/** Submission status */
|
|
142
|
+
status: 'submitted' | 'landed' | 'failed' | 'timeout'
|
|
143
|
+
/** Slot where bundle landed (if confirmed) */
|
|
144
|
+
slot?: number
|
|
145
|
+
/** Error message if failed */
|
|
146
|
+
error?: string
|
|
147
|
+
/** Actual tip paid in lamports */
|
|
148
|
+
tipPaid: number
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Relayed transaction request
|
|
153
|
+
*/
|
|
154
|
+
export interface RelayedTransactionRequest {
|
|
155
|
+
/** Signed transaction to relay */
|
|
156
|
+
transaction: Transaction | VersionedTransaction
|
|
157
|
+
/** Tip amount in lamports (paid by relayer, recovered from user) */
|
|
158
|
+
tipLamports?: number
|
|
159
|
+
/** Whether to wait for confirmation */
|
|
160
|
+
waitForConfirmation?: boolean
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Relayed transaction result
|
|
165
|
+
*/
|
|
166
|
+
export interface RelayedTransactionResult {
|
|
167
|
+
/** Transaction signature */
|
|
168
|
+
signature: string
|
|
169
|
+
/** Bundle ID if submitted via Jito */
|
|
170
|
+
bundleId?: string
|
|
171
|
+
/** Submission status */
|
|
172
|
+
status: 'submitted' | 'confirmed' | 'failed'
|
|
173
|
+
/** Slot where transaction landed */
|
|
174
|
+
slot?: number
|
|
175
|
+
/** Error message if failed */
|
|
176
|
+
error?: string
|
|
177
|
+
/** Whether relayer was used or fell back to direct submission */
|
|
178
|
+
relayed: boolean
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Bundle status from Jito API
|
|
183
|
+
*/
|
|
184
|
+
interface JitoBundleStatus {
|
|
185
|
+
bundleId: string
|
|
186
|
+
status: 'Invalid' | 'Pending' | 'Failed' | 'Landed'
|
|
187
|
+
landedSlot?: number
|
|
188
|
+
error?: string
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// ─── Errors ───────────────────────────────────────────────────────────────────
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Jito relayer error codes
|
|
195
|
+
*/
|
|
196
|
+
export enum JitoRelayerErrorCode {
|
|
197
|
+
BUNDLE_SUBMISSION_FAILED = 'BUNDLE_SUBMISSION_FAILED',
|
|
198
|
+
BUNDLE_TIMEOUT = 'BUNDLE_TIMEOUT',
|
|
199
|
+
BUNDLE_INVALID = 'BUNDLE_INVALID',
|
|
200
|
+
INSUFFICIENT_TIP = 'INSUFFICIENT_TIP',
|
|
201
|
+
CONNECTION_ERROR = 'CONNECTION_ERROR',
|
|
202
|
+
RATE_LIMITED = 'RATE_LIMITED',
|
|
203
|
+
INVALID_TRANSACTION = 'INVALID_TRANSACTION',
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Jito relayer error
|
|
208
|
+
*/
|
|
209
|
+
export class JitoRelayerError extends Error {
|
|
210
|
+
constructor(
|
|
211
|
+
public readonly code: JitoRelayerErrorCode,
|
|
212
|
+
message: string,
|
|
213
|
+
public readonly details?: unknown
|
|
214
|
+
) {
|
|
215
|
+
super(`[${code}] ${message}`)
|
|
216
|
+
this.name = 'JitoRelayerError'
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// ─── Jito Relayer ─────────────────────────────────────────────────────────────
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Jito Relayer for gas abstraction
|
|
224
|
+
*
|
|
225
|
+
* Submits Solana transactions via Jito's MEV infrastructure,
|
|
226
|
+
* enabling gas abstraction for privacy transactions.
|
|
227
|
+
*
|
|
228
|
+
* @example
|
|
229
|
+
* ```typescript
|
|
230
|
+
* import { JitoRelayer } from '@sip-protocol/sdk'
|
|
231
|
+
*
|
|
232
|
+
* const relayer = new JitoRelayer({
|
|
233
|
+
* blockEngineUrl: 'https://ny.mainnet.block-engine.jito.wtf/api/v1',
|
|
234
|
+
* })
|
|
235
|
+
*
|
|
236
|
+
* // Submit a signed transaction via relayer
|
|
237
|
+
* const result = await relayer.relayTransaction({
|
|
238
|
+
* transaction: signedTx,
|
|
239
|
+
* tipLamports: 10_000, // 0.00001 SOL tip
|
|
240
|
+
* })
|
|
241
|
+
*
|
|
242
|
+
* console.log('Transaction relayed:', result.signature)
|
|
243
|
+
* ```
|
|
244
|
+
*/
|
|
245
|
+
export class JitoRelayer {
|
|
246
|
+
private readonly connection: Connection
|
|
247
|
+
private readonly blockEngineUrl: string
|
|
248
|
+
private readonly defaultTipLamports: number
|
|
249
|
+
private readonly debug: boolean
|
|
250
|
+
private readonly maxRetries: number
|
|
251
|
+
private readonly submissionTimeout: number
|
|
252
|
+
|
|
253
|
+
constructor(config: JitoRelayerConfig = {}) {
|
|
254
|
+
this.blockEngineUrl = config.blockEngineUrl ?? JITO_BLOCK_ENGINES.mainnet.ny
|
|
255
|
+
this.connection = new Connection(
|
|
256
|
+
config.rpcUrl ?? 'https://api.mainnet-beta.solana.com',
|
|
257
|
+
'confirmed'
|
|
258
|
+
)
|
|
259
|
+
this.defaultTipLamports = config.defaultTipLamports ?? JITO_DEFAULTS.tipLamports
|
|
260
|
+
this.debug = config.debug ?? false
|
|
261
|
+
this.maxRetries = config.maxRetries ?? JITO_DEFAULTS.maxRetries
|
|
262
|
+
this.submissionTimeout = config.submissionTimeout ?? JITO_DEFAULTS.submissionTimeout
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// ─── Public Methods ─────────────────────────────────────────────────────────
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Submit a bundle of transactions to Jito
|
|
269
|
+
*
|
|
270
|
+
* @param request - Bundle request with transactions and tip
|
|
271
|
+
* @returns Bundle submission result
|
|
272
|
+
*/
|
|
273
|
+
async submitBundle(request: JitoBundleRequest): Promise<JitoBundleResult> {
|
|
274
|
+
const tipLamports = request.tipLamports ?? this.defaultTipLamports
|
|
275
|
+
|
|
276
|
+
this.log('Submitting bundle:', {
|
|
277
|
+
transactionCount: request.transactions.length,
|
|
278
|
+
tipLamports,
|
|
279
|
+
})
|
|
280
|
+
|
|
281
|
+
// Validate bundle size
|
|
282
|
+
if (request.transactions.length > JITO_DEFAULTS.maxBundleSize) {
|
|
283
|
+
throw new JitoRelayerError(
|
|
284
|
+
JitoRelayerErrorCode.INVALID_TRANSACTION,
|
|
285
|
+
`Bundle too large: ${request.transactions.length} > ${JITO_DEFAULTS.maxBundleSize}`
|
|
286
|
+
)
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// Create tip instruction
|
|
290
|
+
const tipInstruction = this.createTipInstruction(request.tipPayer.publicKey, tipLamports)
|
|
291
|
+
|
|
292
|
+
// Get recent blockhash
|
|
293
|
+
const { blockhash, lastValidBlockHeight } = await this.connection.getLatestBlockhash()
|
|
294
|
+
|
|
295
|
+
// Add tip to the first transaction or create a standalone tip tx
|
|
296
|
+
const bundleTransactions = await this.prepareBundleTransactions(
|
|
297
|
+
request.transactions,
|
|
298
|
+
tipInstruction,
|
|
299
|
+
request.tipPayer,
|
|
300
|
+
blockhash
|
|
301
|
+
)
|
|
302
|
+
|
|
303
|
+
// Serialize transactions
|
|
304
|
+
const serializedTxs = bundleTransactions.map(tx => {
|
|
305
|
+
const serialized = tx.serialize()
|
|
306
|
+
return Buffer.from(serialized).toString('base64')
|
|
307
|
+
})
|
|
308
|
+
|
|
309
|
+
// Submit bundle
|
|
310
|
+
let bundleId: string
|
|
311
|
+
let retries = 0
|
|
312
|
+
|
|
313
|
+
while (retries < this.maxRetries) {
|
|
314
|
+
try {
|
|
315
|
+
bundleId = await this.sendBundle(serializedTxs)
|
|
316
|
+
break
|
|
317
|
+
} catch (error) {
|
|
318
|
+
retries++
|
|
319
|
+
if (retries >= this.maxRetries) {
|
|
320
|
+
throw new JitoRelayerError(
|
|
321
|
+
JitoRelayerErrorCode.BUNDLE_SUBMISSION_FAILED,
|
|
322
|
+
`Failed to submit bundle after ${this.maxRetries} attempts`,
|
|
323
|
+
error
|
|
324
|
+
)
|
|
325
|
+
}
|
|
326
|
+
this.log(`Retry ${retries}/${this.maxRetries} after error:`, error)
|
|
327
|
+
await this.sleep(1000 * retries)
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// Extract signatures
|
|
332
|
+
const signatures = bundleTransactions.map(tx => {
|
|
333
|
+
if (tx instanceof VersionedTransaction) {
|
|
334
|
+
return bytesToHex(tx.signatures[0])
|
|
335
|
+
} else {
|
|
336
|
+
return tx.signature?.toString() ?? ''
|
|
337
|
+
}
|
|
338
|
+
})
|
|
339
|
+
|
|
340
|
+
// Wait for confirmation if requested
|
|
341
|
+
if (request.waitForConfirmation) {
|
|
342
|
+
const status = await this.waitForBundleConfirmation(bundleId!, lastValidBlockHeight)
|
|
343
|
+
return {
|
|
344
|
+
bundleId: bundleId!,
|
|
345
|
+
signatures,
|
|
346
|
+
status: status.status === 'Landed' ? 'landed' : 'failed',
|
|
347
|
+
slot: status.landedSlot,
|
|
348
|
+
error: status.error,
|
|
349
|
+
tipPaid: tipLamports,
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
return {
|
|
354
|
+
bundleId: bundleId!,
|
|
355
|
+
signatures,
|
|
356
|
+
status: 'submitted',
|
|
357
|
+
tipPaid: tipLamports,
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* Relay a single transaction via Jito
|
|
363
|
+
*
|
|
364
|
+
* This is the main method for gas abstraction - submit a transaction
|
|
365
|
+
* through the relayer instead of paying gas directly.
|
|
366
|
+
*
|
|
367
|
+
* @param request - Transaction to relay
|
|
368
|
+
* @returns Relay result
|
|
369
|
+
*/
|
|
370
|
+
async relayTransaction(
|
|
371
|
+
request: RelayedTransactionRequest
|
|
372
|
+
): Promise<RelayedTransactionResult> {
|
|
373
|
+
this.log('Relaying transaction')
|
|
374
|
+
|
|
375
|
+
try {
|
|
376
|
+
// For single transaction relay, we need to handle it differently
|
|
377
|
+
// The transaction should already be signed by the user
|
|
378
|
+
// We add it to a bundle with a tip transaction
|
|
379
|
+
|
|
380
|
+
const serializedTx = Buffer.from(request.transaction.serialize()).toString('base64')
|
|
381
|
+
|
|
382
|
+
// Submit as single-tx bundle
|
|
383
|
+
const bundleId = await this.sendBundle([serializedTx])
|
|
384
|
+
|
|
385
|
+
// Get signature
|
|
386
|
+
let signature: string
|
|
387
|
+
if (request.transaction instanceof VersionedTransaction) {
|
|
388
|
+
signature = bytesToHex(request.transaction.signatures[0])
|
|
389
|
+
} else {
|
|
390
|
+
signature = request.transaction.signature?.toString() ?? ''
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
// Wait for confirmation if requested
|
|
394
|
+
if (request.waitForConfirmation) {
|
|
395
|
+
const { lastValidBlockHeight } = await this.connection.getLatestBlockhash()
|
|
396
|
+
const status = await this.waitForBundleConfirmation(bundleId, lastValidBlockHeight)
|
|
397
|
+
|
|
398
|
+
return {
|
|
399
|
+
signature,
|
|
400
|
+
bundleId,
|
|
401
|
+
status: status.status === 'Landed' ? 'confirmed' : 'failed',
|
|
402
|
+
slot: status.landedSlot,
|
|
403
|
+
error: status.error,
|
|
404
|
+
relayed: true,
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
return {
|
|
409
|
+
signature,
|
|
410
|
+
bundleId,
|
|
411
|
+
status: 'submitted',
|
|
412
|
+
relayed: true,
|
|
413
|
+
}
|
|
414
|
+
} catch (error) {
|
|
415
|
+
// Fallback to direct submission
|
|
416
|
+
this.log('Relayer failed, falling back to direct submission:', error)
|
|
417
|
+
return this.directSubmit(request.transaction, request.waitForConfirmation)
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
/**
|
|
422
|
+
* Check if Jito relayer is available
|
|
423
|
+
*/
|
|
424
|
+
async isAvailable(): Promise<boolean> {
|
|
425
|
+
try {
|
|
426
|
+
const response = await fetch(`${this.blockEngineUrl}/health`, {
|
|
427
|
+
method: 'GET',
|
|
428
|
+
signal: AbortSignal.timeout(5000),
|
|
429
|
+
})
|
|
430
|
+
return response.ok
|
|
431
|
+
} catch {
|
|
432
|
+
return false
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
/**
|
|
437
|
+
* Get current tip floor (minimum tip for inclusion)
|
|
438
|
+
*/
|
|
439
|
+
async getTipFloor(): Promise<number> {
|
|
440
|
+
// In production, this would query Jito's tip floor endpoint
|
|
441
|
+
// For now, return a conservative default
|
|
442
|
+
return JITO_DEFAULTS.tipLamports
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
/**
|
|
446
|
+
* Get a random tip account
|
|
447
|
+
*/
|
|
448
|
+
getRandomTipAccount(): PublicKey {
|
|
449
|
+
const index = Math.floor(Math.random() * JITO_TIP_ACCOUNTS.length)
|
|
450
|
+
return new PublicKey(JITO_TIP_ACCOUNTS[index])
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
// ─── Private Methods ────────────────────────────────────────────────────────
|
|
454
|
+
|
|
455
|
+
/**
|
|
456
|
+
* Create tip instruction
|
|
457
|
+
*/
|
|
458
|
+
private createTipInstruction(
|
|
459
|
+
payer: PublicKey,
|
|
460
|
+
tipLamports: number
|
|
461
|
+
): TransactionInstruction {
|
|
462
|
+
const tipAccount = this.getRandomTipAccount()
|
|
463
|
+
return SystemProgram.transfer({
|
|
464
|
+
fromPubkey: payer,
|
|
465
|
+
toPubkey: tipAccount,
|
|
466
|
+
lamports: tipLamports,
|
|
467
|
+
})
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
/**
|
|
471
|
+
* Prepare transactions for bundle submission
|
|
472
|
+
*/
|
|
473
|
+
private async prepareBundleTransactions(
|
|
474
|
+
transactions: (Transaction | VersionedTransaction)[],
|
|
475
|
+
tipInstruction: TransactionInstruction,
|
|
476
|
+
tipPayer: Keypair,
|
|
477
|
+
blockhash: string
|
|
478
|
+
): Promise<(Transaction | VersionedTransaction)[]> {
|
|
479
|
+
// Create tip transaction
|
|
480
|
+
const tipTx = new Transaction()
|
|
481
|
+
tipTx.add(tipInstruction)
|
|
482
|
+
tipTx.recentBlockhash = blockhash
|
|
483
|
+
tipTx.feePayer = tipPayer.publicKey
|
|
484
|
+
tipTx.sign(tipPayer)
|
|
485
|
+
|
|
486
|
+
// Return tip tx first, then user transactions
|
|
487
|
+
return [tipTx, ...transactions]
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
/**
|
|
491
|
+
* Send bundle to Jito block engine
|
|
492
|
+
*/
|
|
493
|
+
private async sendBundle(serializedTransactions: string[]): Promise<string> {
|
|
494
|
+
const response = await fetch(`${this.blockEngineUrl}/bundles`, {
|
|
495
|
+
method: 'POST',
|
|
496
|
+
headers: {
|
|
497
|
+
'Content-Type': 'application/json',
|
|
498
|
+
},
|
|
499
|
+
body: JSON.stringify({
|
|
500
|
+
jsonrpc: '2.0',
|
|
501
|
+
id: 1,
|
|
502
|
+
method: 'sendBundle',
|
|
503
|
+
params: [serializedTransactions],
|
|
504
|
+
}),
|
|
505
|
+
signal: AbortSignal.timeout(this.submissionTimeout),
|
|
506
|
+
})
|
|
507
|
+
|
|
508
|
+
if (!response.ok) {
|
|
509
|
+
const text = await response.text()
|
|
510
|
+
throw new JitoRelayerError(
|
|
511
|
+
JitoRelayerErrorCode.CONNECTION_ERROR,
|
|
512
|
+
`Block engine returned ${response.status}: ${text}`
|
|
513
|
+
)
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
const result = await response.json() as {
|
|
517
|
+
result?: string
|
|
518
|
+
error?: { message: string; code: number }
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
if (result.error) {
|
|
522
|
+
throw new JitoRelayerError(
|
|
523
|
+
JitoRelayerErrorCode.BUNDLE_SUBMISSION_FAILED,
|
|
524
|
+
result.error.message,
|
|
525
|
+
result.error
|
|
526
|
+
)
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
return result.result ?? ''
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
/**
|
|
533
|
+
* Wait for bundle confirmation
|
|
534
|
+
*/
|
|
535
|
+
private async waitForBundleConfirmation(
|
|
536
|
+
bundleId: string,
|
|
537
|
+
lastValidBlockHeight: number
|
|
538
|
+
): Promise<JitoBundleStatus> {
|
|
539
|
+
const startTime = Date.now()
|
|
540
|
+
|
|
541
|
+
while (Date.now() - startTime < JITO_DEFAULTS.confirmationTimeout) {
|
|
542
|
+
// Check current block height
|
|
543
|
+
const currentBlockHeight = await this.connection.getBlockHeight()
|
|
544
|
+
|
|
545
|
+
if (currentBlockHeight > lastValidBlockHeight) {
|
|
546
|
+
return {
|
|
547
|
+
bundleId,
|
|
548
|
+
status: 'Failed',
|
|
549
|
+
error: 'Bundle expired (blockhash invalid)',
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
// Check bundle status
|
|
554
|
+
const status = await this.getBundleStatus(bundleId)
|
|
555
|
+
|
|
556
|
+
if (status.status === 'Landed' || status.status === 'Failed' || status.status === 'Invalid') {
|
|
557
|
+
return status
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
await this.sleep(2000)
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
return {
|
|
564
|
+
bundleId,
|
|
565
|
+
status: 'Failed',
|
|
566
|
+
error: 'Confirmation timeout',
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
/**
|
|
571
|
+
* Get bundle status from Jito
|
|
572
|
+
*/
|
|
573
|
+
private async getBundleStatus(bundleId: string): Promise<JitoBundleStatus> {
|
|
574
|
+
try {
|
|
575
|
+
const response = await fetch(`${this.blockEngineUrl}/bundles`, {
|
|
576
|
+
method: 'POST',
|
|
577
|
+
headers: {
|
|
578
|
+
'Content-Type': 'application/json',
|
|
579
|
+
},
|
|
580
|
+
body: JSON.stringify({
|
|
581
|
+
jsonrpc: '2.0',
|
|
582
|
+
id: 1,
|
|
583
|
+
method: 'getBundleStatuses',
|
|
584
|
+
params: [[bundleId]],
|
|
585
|
+
}),
|
|
586
|
+
signal: AbortSignal.timeout(10000),
|
|
587
|
+
})
|
|
588
|
+
|
|
589
|
+
const result = await response.json() as {
|
|
590
|
+
result?: {
|
|
591
|
+
value: Array<{
|
|
592
|
+
bundle_id: string
|
|
593
|
+
status: string
|
|
594
|
+
landed_slot?: number
|
|
595
|
+
}>
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
const bundleStatus = result.result?.value?.[0]
|
|
600
|
+
|
|
601
|
+
if (!bundleStatus) {
|
|
602
|
+
return { bundleId, status: 'Pending' }
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
return {
|
|
606
|
+
bundleId,
|
|
607
|
+
status: bundleStatus.status as 'Invalid' | 'Pending' | 'Failed' | 'Landed',
|
|
608
|
+
landedSlot: bundleStatus.landed_slot,
|
|
609
|
+
}
|
|
610
|
+
} catch {
|
|
611
|
+
return { bundleId, status: 'Pending' }
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
/**
|
|
616
|
+
* Direct submission fallback
|
|
617
|
+
*/
|
|
618
|
+
private async directSubmit(
|
|
619
|
+
transaction: Transaction | VersionedTransaction,
|
|
620
|
+
waitForConfirmation?: boolean
|
|
621
|
+
): Promise<RelayedTransactionResult> {
|
|
622
|
+
const signature = await this.connection.sendRawTransaction(
|
|
623
|
+
transaction.serialize(),
|
|
624
|
+
{ skipPreflight: false, maxRetries: 3 }
|
|
625
|
+
)
|
|
626
|
+
|
|
627
|
+
if (waitForConfirmation) {
|
|
628
|
+
const { blockhash, lastValidBlockHeight } = await this.connection.getLatestBlockhash()
|
|
629
|
+
const confirmation = await this.connection.confirmTransaction({
|
|
630
|
+
signature,
|
|
631
|
+
blockhash,
|
|
632
|
+
lastValidBlockHeight,
|
|
633
|
+
}, 'confirmed')
|
|
634
|
+
|
|
635
|
+
return {
|
|
636
|
+
signature,
|
|
637
|
+
status: confirmation.value.err ? 'failed' : 'confirmed',
|
|
638
|
+
error: confirmation.value.err?.toString(),
|
|
639
|
+
relayed: false,
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
return {
|
|
644
|
+
signature,
|
|
645
|
+
status: 'submitted',
|
|
646
|
+
relayed: false,
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
/**
|
|
651
|
+
* Log debug message
|
|
652
|
+
*/
|
|
653
|
+
private log(message: string, ...args: unknown[]): void {
|
|
654
|
+
if (this.debug) {
|
|
655
|
+
console.log(`[JitoRelayer] ${message}`, ...args)
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
/**
|
|
660
|
+
* Sleep utility
|
|
661
|
+
*/
|
|
662
|
+
private sleep(ms: number): Promise<void> {
|
|
663
|
+
return new Promise(resolve => setTimeout(resolve, ms))
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
// ─── Factory ──────────────────────────────────────────────────────────────────
|
|
668
|
+
|
|
669
|
+
/**
|
|
670
|
+
* Create a Jito relayer instance
|
|
671
|
+
*
|
|
672
|
+
* @param config - Relayer configuration
|
|
673
|
+
* @returns Jito relayer instance
|
|
674
|
+
*/
|
|
675
|
+
export function createJitoRelayer(config?: JitoRelayerConfig): JitoRelayer {
|
|
676
|
+
return new JitoRelayer(config)
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
/**
|
|
680
|
+
* Create a mainnet Jito relayer with NY block engine
|
|
681
|
+
*/
|
|
682
|
+
export function createMainnetRelayer(rpcUrl?: string): JitoRelayer {
|
|
683
|
+
return new JitoRelayer({
|
|
684
|
+
blockEngineUrl: JITO_BLOCK_ENGINES.mainnet.ny,
|
|
685
|
+
rpcUrl: rpcUrl ?? 'https://api.mainnet-beta.solana.com',
|
|
686
|
+
})
|
|
687
|
+
}
|