@kestrelfi/lyc-sdk 1.0.1 → 1.0.3
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 +32 -0
- package/dist/carry-XU3WUD22.mjs +20 -0
- package/dist/carry-XU3WUD22.mjs.map +1 -0
- package/dist/chunk-2T23QQCX.mjs +3707 -0
- package/dist/chunk-2T23QQCX.mjs.map +1 -0
- package/dist/chunk-GOW6CARW.mjs +3969 -0
- package/dist/chunk-GOW6CARW.mjs.map +1 -0
- package/dist/chunk-ZPXXY3QV.mjs +9330 -0
- package/dist/chunk-ZPXXY3QV.mjs.map +1 -0
- package/dist/{sdks/long-yield-carry/src/idl/long_yield_carry.d.ts → core-DP6wfpME.d.mts} +3242 -84
- package/dist/core-DP6wfpME.d.ts +10485 -0
- package/dist/core.d.mts +8 -0
- package/dist/core.d.ts +8 -0
- package/dist/core.js +12348 -0
- package/dist/core.js.map +1 -0
- package/dist/core.mjs +72 -0
- package/dist/core.mjs.map +1 -0
- package/dist/index.d.mts +2537 -0
- package/dist/index.d.ts +2537 -0
- package/dist/index.js +23884 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +5898 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +56 -10
- package/.env.example +0 -11
- package/dist/sdks/long-yield-carry/scripts/asyncBurn.d.ts +0 -1
- package/dist/sdks/long-yield-carry/scripts/asyncBurn.js +0 -117
- package/dist/sdks/long-yield-carry/scripts/burnToken.d.ts +0 -1
- package/dist/sdks/long-yield-carry/scripts/burnToken.js +0 -98
- package/dist/sdks/long-yield-carry/scripts/claimIncentives.d.ts +0 -1
- package/dist/sdks/long-yield-carry/scripts/claimIncentives.js +0 -108
- package/dist/sdks/long-yield-carry/scripts/closeCpiPlans.d.ts +0 -1
- package/dist/sdks/long-yield-carry/scripts/closeCpiPlans.js +0 -93
- package/dist/sdks/long-yield-carry/scripts/collectInterest.d.ts +0 -1
- package/dist/sdks/long-yield-carry/scripts/collectInterest.js +0 -164
- package/dist/sdks/long-yield-carry/scripts/collectProtocolFees.d.ts +0 -1
- package/dist/sdks/long-yield-carry/scripts/collectProtocolFees.js +0 -120
- package/dist/sdks/long-yield-carry/scripts/computeOptimalAllocations.d.ts +0 -1
- package/dist/sdks/long-yield-carry/scripts/computeOptimalAllocations.js +0 -84
- package/dist/sdks/long-yield-carry/scripts/createToken.d.ts +0 -1
- package/dist/sdks/long-yield-carry/scripts/createToken.js +0 -76
- package/dist/sdks/long-yield-carry/scripts/createTokenLendingPosition.d.ts +0 -1
- package/dist/sdks/long-yield-carry/scripts/createTokenLendingPosition.js +0 -157
- package/dist/sdks/long-yield-carry/scripts/createYieldingBank.d.ts +0 -1
- package/dist/sdks/long-yield-carry/scripts/createYieldingBank.js +0 -69
- package/dist/sdks/long-yield-carry/scripts/decreaseCarryPositions.d.ts +0 -1
- package/dist/sdks/long-yield-carry/scripts/decreaseCarryPositions.js +0 -247
- package/dist/sdks/long-yield-carry/scripts/depositUnlentCollateral.d.ts +0 -1
- package/dist/sdks/long-yield-carry/scripts/depositUnlentCollateral.js +0 -90
- package/dist/sdks/long-yield-carry/scripts/emergency/deleverageAll.d.ts +0 -1
- package/dist/sdks/long-yield-carry/scripts/emergency/deleverageAll.js +0 -202
- package/dist/sdks/long-yield-carry/scripts/emergency/triggerCircuitBreaker.d.ts +0 -1
- package/dist/sdks/long-yield-carry/scripts/emergency/triggerCircuitBreaker.js +0 -68
- package/dist/sdks/long-yield-carry/scripts/env.d.ts +0 -1
- package/dist/sdks/long-yield-carry/scripts/env.js +0 -8
- package/dist/sdks/long-yield-carry/scripts/findTxs.d.ts +0 -1
- package/dist/sdks/long-yield-carry/scripts/findTxs.js +0 -143
- package/dist/sdks/long-yield-carry/scripts/increaseCarryPositions.d.ts +0 -1
- package/dist/sdks/long-yield-carry/scripts/increaseCarryPositions.js +0 -112
- package/dist/sdks/long-yield-carry/scripts/inspect/format.d.ts +0 -13
- package/dist/sdks/long-yield-carry/scripts/inspect/format.js +0 -363
- package/dist/sdks/long-yield-carry/scripts/inspect.d.ts +0 -1
- package/dist/sdks/long-yield-carry/scripts/inspect.js +0 -108
- package/dist/sdks/long-yield-carry/scripts/localUtils.d.ts +0 -53
- package/dist/sdks/long-yield-carry/scripts/localUtils.js +0 -191
- package/dist/sdks/long-yield-carry/scripts/mintToken.d.ts +0 -1
- package/dist/sdks/long-yield-carry/scripts/mintToken.js +0 -103
- package/dist/sdks/long-yield-carry/scripts/processAsyncBurns.d.ts +0 -1
- package/dist/sdks/long-yield-carry/scripts/processAsyncBurns.js +0 -76
- package/dist/sdks/long-yield-carry/scripts/rebalanceToken.d.ts +0 -1
- package/dist/sdks/long-yield-carry/scripts/rebalanceToken.js +0 -210
- package/dist/sdks/long-yield-carry/scripts/rebalanceYieldingBank.d.ts +0 -1
- package/dist/sdks/long-yield-carry/scripts/rebalanceYieldingBank.js +0 -149
- package/dist/sdks/long-yield-carry/scripts/recollateralizeLoss.d.ts +0 -1
- package/dist/sdks/long-yield-carry/scripts/recollateralizeLoss.js +0 -64
- package/dist/sdks/long-yield-carry/scripts/refresh.d.ts +0 -1
- package/dist/sdks/long-yield-carry/scripts/refresh.js +0 -101
- package/dist/sdks/long-yield-carry/scripts/updateFees.d.ts +0 -1
- package/dist/sdks/long-yield-carry/scripts/updateFees.js +0 -369
- package/dist/sdks/long-yield-carry/scripts/updateGeneralLut.d.ts +0 -1
- package/dist/sdks/long-yield-carry/scripts/updateGeneralLut.js +0 -27
- package/dist/sdks/long-yield-carry/scripts/updateLendingPositionConfig.d.ts +0 -1
- package/dist/sdks/long-yield-carry/scripts/updateLendingPositionConfig.js +0 -127
- package/dist/sdks/long-yield-carry/scripts/updateTokenLuts.d.ts +0 -1
- package/dist/sdks/long-yield-carry/scripts/updateTokenLuts.js +0 -27
- package/dist/sdks/long-yield-carry/scripts/updateTokenMetadata.d.ts +0 -1
- package/dist/sdks/long-yield-carry/scripts/updateTokenMetadata.js +0 -194
- package/dist/sdks/long-yield-carry/scripts/updateYieldingBankConfig.d.ts +0 -1
- package/dist/sdks/long-yield-carry/scripts/updateYieldingBankConfig.js +0 -84
- package/dist/sdks/long-yield-carry/scripts/withdrawUnlentCollateral.d.ts +0 -1
- package/dist/sdks/long-yield-carry/scripts/withdrawUnlentCollateral.js +0 -140
- package/dist/sdks/long-yield-carry/src/client/account.d.ts +0 -152
- package/dist/sdks/long-yield-carry/src/client/account.js +0 -349
- package/dist/sdks/long-yield-carry/src/client/builders/args.d.ts +0 -299
- package/dist/sdks/long-yield-carry/src/client/builders/args.js +0 -2
- package/dist/sdks/long-yield-carry/src/client/builders/asyncBurnBuilder.d.ts +0 -20
- package/dist/sdks/long-yield-carry/src/client/builders/asyncBurnBuilder.js +0 -212
- package/dist/sdks/long-yield-carry/src/client/builders/base.d.ts +0 -77
- package/dist/sdks/long-yield-carry/src/client/builders/base.js +0 -191
- package/dist/sdks/long-yield-carry/src/client/builders/burnTokenBuilder.d.ts +0 -18
- package/dist/sdks/long-yield-carry/src/client/builders/burnTokenBuilder.js +0 -165
- package/dist/sdks/long-yield-carry/src/client/builders/claimIncentivesBuilder.d.ts +0 -9
- package/dist/sdks/long-yield-carry/src/client/builders/claimIncentivesBuilder.js +0 -135
- package/dist/sdks/long-yield-carry/src/client/builders/collectFeesBuilder.d.ts +0 -14
- package/dist/sdks/long-yield-carry/src/client/builders/collectFeesBuilder.js +0 -50
- package/dist/sdks/long-yield-carry/src/client/builders/collectInterestBuilder.d.ts +0 -8
- package/dist/sdks/long-yield-carry/src/client/builders/collectInterestBuilder.js +0 -86
- package/dist/sdks/long-yield-carry/src/client/builders/createCpiPlanBuilder.d.ts +0 -6
- package/dist/sdks/long-yield-carry/src/client/builders/createCpiPlanBuilder.js +0 -22
- package/dist/sdks/long-yield-carry/src/client/builders/createTokenBuilder.d.ts +0 -7
- package/dist/sdks/long-yield-carry/src/client/builders/createTokenBuilder.js +0 -64
- package/dist/sdks/long-yield-carry/src/client/builders/createTokenLendingPositionBuilder.d.ts +0 -10
- package/dist/sdks/long-yield-carry/src/client/builders/createTokenLendingPositionBuilder.js +0 -138
- package/dist/sdks/long-yield-carry/src/client/builders/createYieldingBankAllocationBuilder.d.ts +0 -7
- package/dist/sdks/long-yield-carry/src/client/builders/createYieldingBankAllocationBuilder.js +0 -29
- package/dist/sdks/long-yield-carry/src/client/builders/createYieldingBankBuilder.d.ts +0 -7
- package/dist/sdks/long-yield-carry/src/client/builders/createYieldingBankBuilder.js +0 -39
- package/dist/sdks/long-yield-carry/src/client/builders/decreaseCarryPositionBuilder.d.ts +0 -30
- package/dist/sdks/long-yield-carry/src/client/builders/decreaseCarryPositionBuilder.js +0 -99
- package/dist/sdks/long-yield-carry/src/client/builders/depositUnlentCollateralBuilder.d.ts +0 -8
- package/dist/sdks/long-yield-carry/src/client/builders/depositUnlentCollateralBuilder.js +0 -64
- package/dist/sdks/long-yield-carry/src/client/builders/increaseCarryPositionBuilder.d.ts +0 -8
- package/dist/sdks/long-yield-carry/src/client/builders/increaseCarryPositionBuilder.js +0 -73
- package/dist/sdks/long-yield-carry/src/client/builders/index.d.ts +0 -28
- package/dist/sdks/long-yield-carry/src/client/builders/index.js +0 -62
- package/dist/sdks/long-yield-carry/src/client/builders/mintTokenBuilder.d.ts +0 -8
- package/dist/sdks/long-yield-carry/src/client/builders/mintTokenBuilder.js +0 -95
- package/dist/sdks/long-yield-carry/src/client/builders/rebalanceTokenBuilder.d.ts +0 -11
- package/dist/sdks/long-yield-carry/src/client/builders/rebalanceTokenBuilder.js +0 -255
- package/dist/sdks/long-yield-carry/src/client/builders/rebalanceYieldingBankBuilder.d.ts +0 -8
- package/dist/sdks/long-yield-carry/src/client/builders/rebalanceYieldingBankBuilder.js +0 -75
- package/dist/sdks/long-yield-carry/src/client/builders/recollateralizeLossBuilder.d.ts +0 -12
- package/dist/sdks/long-yield-carry/src/client/builders/recollateralizeLossBuilder.js +0 -220
- package/dist/sdks/long-yield-carry/src/client/builders/refreshTokenStateBuilder.d.ts +0 -9
- package/dist/sdks/long-yield-carry/src/client/builders/refreshTokenStateBuilder.js +0 -112
- package/dist/sdks/long-yield-carry/src/client/builders/refreshTokensBuilder.d.ts +0 -9
- package/dist/sdks/long-yield-carry/src/client/builders/refreshTokensBuilder.js +0 -59
- package/dist/sdks/long-yield-carry/src/client/builders/refreshYieldingBankBuilder.d.ts +0 -8
- package/dist/sdks/long-yield-carry/src/client/builders/refreshYieldingBankBuilder.js +0 -29
- package/dist/sdks/long-yield-carry/src/client/builders/resetTokenBurnRateLimitBuilder.d.ts +0 -7
- package/dist/sdks/long-yield-carry/src/client/builders/resetTokenBurnRateLimitBuilder.js +0 -19
- package/dist/sdks/long-yield-carry/src/client/builders/setTokenCircuitBreakerBuilder.d.ts +0 -11
- package/dist/sdks/long-yield-carry/src/client/builders/setTokenCircuitBreakerBuilder.js +0 -31
- package/dist/sdks/long-yield-carry/src/client/builders/setYieldingBankCircuitBreakerBuilder.d.ts +0 -8
- package/dist/sdks/long-yield-carry/src/client/builders/setYieldingBankCircuitBreakerBuilder.js +0 -28
- package/dist/sdks/long-yield-carry/src/client/builders/updateLendingPositionConfigBuilder.d.ts +0 -10
- package/dist/sdks/long-yield-carry/src/client/builders/updateLendingPositionConfigBuilder.js +0 -30
- package/dist/sdks/long-yield-carry/src/client/builders/updateTokenConfigurationBuilder.d.ts +0 -11
- package/dist/sdks/long-yield-carry/src/client/builders/updateTokenConfigurationBuilder.js +0 -47
- package/dist/sdks/long-yield-carry/src/client/builders/updateTokenMetadataBuilder.d.ts +0 -7
- package/dist/sdks/long-yield-carry/src/client/builders/updateTokenMetadataBuilder.js +0 -24
- package/dist/sdks/long-yield-carry/src/client/builders/updateYieldingBankConfigBuilder.d.ts +0 -10
- package/dist/sdks/long-yield-carry/src/client/builders/updateYieldingBankConfigBuilder.js +0 -31
- package/dist/sdks/long-yield-carry/src/client/builders/utils.d.ts +0 -4
- package/dist/sdks/long-yield-carry/src/client/builders/utils.js +0 -20
- package/dist/sdks/long-yield-carry/src/client/client.d.ts +0 -115
- package/dist/sdks/long-yield-carry/src/client/client.js +0 -166
- package/dist/sdks/long-yield-carry/src/client/externalLiquidityResolver.d.ts +0 -13
- package/dist/sdks/long-yield-carry/src/client/externalLiquidityResolver.js +0 -34
- package/dist/sdks/long-yield-carry/src/client/index.d.ts +0 -10
- package/dist/sdks/long-yield-carry/src/client/index.js +0 -33
- package/dist/sdks/long-yield-carry/src/client/lendingPlatformClients.d.ts +0 -19
- package/dist/sdks/long-yield-carry/src/client/lendingPlatformClients.js +0 -33
- package/dist/sdks/long-yield-carry/src/client/pda.d.ts +0 -33
- package/dist/sdks/long-yield-carry/src/client/pda.js +0 -79
- package/dist/sdks/long-yield-carry/src/client/plans/collectInterest.d.ts +0 -24
- package/dist/sdks/long-yield-carry/src/client/plans/collectInterest.js +0 -150
- package/dist/sdks/long-yield-carry/src/client/plans/decreaseCarryPosition.d.ts +0 -12
- package/dist/sdks/long-yield-carry/src/client/plans/decreaseCarryPosition.js +0 -140
- package/dist/sdks/long-yield-carry/src/client/routes/collectInterest.d.ts +0 -13
- package/dist/sdks/long-yield-carry/src/client/routes/collectInterest.js +0 -39
- package/dist/sdks/long-yield-carry/src/client/transaction.d.ts +0 -41
- package/dist/sdks/long-yield-carry/src/client/transaction.js +0 -55
- package/dist/sdks/long-yield-carry/src/client/types/builders.d.ts +0 -18
- package/dist/sdks/long-yield-carry/src/client/types/builders.js +0 -2
- package/dist/sdks/long-yield-carry/src/client/types/enums.d.ts +0 -22
- package/dist/sdks/long-yield-carry/src/client/types/enums.js +0 -48
- package/dist/sdks/long-yield-carry/src/client/types/general.d.ts +0 -98
- package/dist/sdks/long-yield-carry/src/client/types/general.js +0 -2
- package/dist/sdks/long-yield-carry/src/client/types/index.d.ts +0 -6
- package/dist/sdks/long-yield-carry/src/client/types/index.js +0 -22
- package/dist/sdks/long-yield-carry/src/client/types/ix.d.ts +0 -352
- package/dist/sdks/long-yield-carry/src/client/types/ix.js +0 -2
- package/dist/sdks/long-yield-carry/src/client/types/planTypes/collectInterest.d.ts +0 -91
- package/dist/sdks/long-yield-carry/src/client/types/planTypes/collectInterest.js +0 -2
- package/dist/sdks/long-yield-carry/src/client/types/planTypes/common.d.ts +0 -28
- package/dist/sdks/long-yield-carry/src/client/types/planTypes/common.js +0 -2
- package/dist/sdks/long-yield-carry/src/client/types/planTypes/decreaseCarryPosition.d.ts +0 -128
- package/dist/sdks/long-yield-carry/src/client/types/planTypes/decreaseCarryPosition.js +0 -2
- package/dist/sdks/long-yield-carry/src/client/types/planTypes/index.d.ts +0 -3
- package/dist/sdks/long-yield-carry/src/client/types/planTypes/index.js +0 -19
- package/dist/sdks/long-yield-carry/src/client/types/tx.d.ts +0 -339
- package/dist/sdks/long-yield-carry/src/client/types/tx.js +0 -2
- package/dist/sdks/long-yield-carry/src/constants/configs/allocations.d.ts +0 -3
- package/dist/sdks/long-yield-carry/src/constants/configs/allocations.js +0 -23
- package/dist/sdks/long-yield-carry/src/constants/configs/carryTradePresets.d.ts +0 -58
- package/dist/sdks/long-yield-carry/src/constants/configs/carryTradePresets.js +0 -116
- package/dist/sdks/long-yield-carry/src/constants/configs/index.d.ts +0 -2
- package/dist/sdks/long-yield-carry/src/constants/configs/index.js +0 -18
- package/dist/sdks/long-yield-carry/src/constants/general.d.ts +0 -70
- package/dist/sdks/long-yield-carry/src/constants/general.js +0 -107
- package/dist/sdks/long-yield-carry/src/constants/index.d.ts +0 -3
- package/dist/sdks/long-yield-carry/src/constants/index.js +0 -19
- package/dist/sdks/long-yield-carry/src/constants/lycTokenMetadata.d.ts +0 -36
- package/dist/sdks/long-yield-carry/src/constants/lycTokenMetadata.js +0 -41
- package/dist/sdks/long-yield-carry/src/decoders/decodeTransaction.d.ts +0 -86
- package/dist/sdks/long-yield-carry/src/decoders/decodeTransaction.js +0 -230
- package/dist/sdks/long-yield-carry/src/decoders/discriminators.d.ts +0 -8
- package/dist/sdks/long-yield-carry/src/decoders/discriminators.js +0 -11
- package/dist/sdks/long-yield-carry/src/decoders/idlAccounts.d.ts +0 -29
- package/dist/sdks/long-yield-carry/src/decoders/idlAccounts.js +0 -57
- package/dist/sdks/long-yield-carry/src/decoders/index.d.ts +0 -6
- package/dist/sdks/long-yield-carry/src/decoders/index.js +0 -14
- package/dist/sdks/long-yield-carry/src/decoders/innerCpis.d.ts +0 -68
- package/dist/sdks/long-yield-carry/src/decoders/innerCpis.js +0 -225
- package/dist/sdks/long-yield-carry/src/decoders/lycInstructionNames.d.ts +0 -6
- package/dist/sdks/long-yield-carry/src/decoders/lycInstructionNames.js +0 -73
- package/dist/sdks/long-yield-carry/src/decoders/programIds.d.ts +0 -4
- package/dist/sdks/long-yield-carry/src/decoders/programIds.js +0 -11
- package/dist/sdks/long-yield-carry/src/decoders/solana.d.ts +0 -7
- package/dist/sdks/long-yield-carry/src/decoders/solana.js +0 -30
- package/dist/sdks/long-yield-carry/src/decoders/transactionPayload.d.ts +0 -41
- package/dist/sdks/long-yield-carry/src/decoders/transactionPayload.js +0 -6
- package/dist/sdks/long-yield-carry/src/decoders/types.d.ts +0 -58
- package/dist/sdks/long-yield-carry/src/decoders/types.js +0 -2
- package/dist/sdks/long-yield-carry/src/errors.d.ts +0 -69
- package/dist/sdks/long-yield-carry/src/errors.js +0 -183
- package/dist/sdks/long-yield-carry/src/idl/long_yield_carry.js +0 -7323
- package/dist/sdks/long-yield-carry/src/index.d.ts +0 -10
- package/dist/sdks/long-yield-carry/src/index.js +0 -25
- package/dist/sdks/long-yield-carry/src/metrics/index.d.ts +0 -1
- package/dist/sdks/long-yield-carry/src/metrics/index.js +0 -17
- package/dist/sdks/long-yield-carry/src/metrics/protocolMetrics.d.ts +0 -276
- package/dist/sdks/long-yield-carry/src/metrics/protocolMetrics.js +0 -547
- package/dist/sdks/long-yield-carry/src/models/index.d.ts +0 -3
- package/dist/sdks/long-yield-carry/src/models/index.js +0 -7
- package/dist/sdks/long-yield-carry/src/models/lycToken.d.ts +0 -156
- package/dist/sdks/long-yield-carry/src/models/lycToken.js +0 -288
- package/dist/sdks/long-yield-carry/src/models/yieldingBank.d.ts +0 -52
- package/dist/sdks/long-yield-carry/src/models/yieldingBank.js +0 -109
- package/dist/sdks/long-yield-carry/src/services/allocation/allocationService.d.ts +0 -106
- package/dist/sdks/long-yield-carry/src/services/allocation/allocationService.js +0 -589
- package/dist/sdks/long-yield-carry/src/services/allocation/index.d.ts +0 -2
- package/dist/sdks/long-yield-carry/src/services/allocation/index.js +0 -18
- package/dist/sdks/long-yield-carry/src/services/allocation/types.d.ts +0 -25
- package/dist/sdks/long-yield-carry/src/services/allocation/types.js +0 -2
- package/dist/sdks/long-yield-carry/src/services/carry/carryAllocationConfig.d.ts +0 -103
- package/dist/sdks/long-yield-carry/src/services/carry/carryAllocationConfig.js +0 -146
- package/dist/sdks/long-yield-carry/src/services/carry/index.d.ts +0 -2
- package/dist/sdks/long-yield-carry/src/services/carry/index.js +0 -18
- package/dist/sdks/long-yield-carry/src/services/carry/lycLendingPositionManager.d.ts +0 -39
- package/dist/sdks/long-yield-carry/src/services/carry/lycLendingPositionManager.js +0 -100
- package/dist/sdks/long-yield-carry/src/services/index.d.ts +0 -5
- package/dist/sdks/long-yield-carry/src/services/index.js +0 -21
- package/dist/sdks/long-yield-carry/src/services/lendingPosition/index.d.ts +0 -2
- package/dist/sdks/long-yield-carry/src/services/lendingPosition/index.js +0 -5
- package/dist/sdks/long-yield-carry/src/services/lendingPosition/lendingPositionService.d.ts +0 -88
- package/dist/sdks/long-yield-carry/src/services/lendingPosition/lendingPositionService.js +0 -229
- package/dist/sdks/long-yield-carry/src/services/rebalance/index.d.ts +0 -2
- package/dist/sdks/long-yield-carry/src/services/rebalance/index.js +0 -18
- package/dist/sdks/long-yield-carry/src/services/rebalance/token/index.d.ts +0 -1
- package/dist/sdks/long-yield-carry/src/services/rebalance/token/index.js +0 -17
- package/dist/sdks/long-yield-carry/src/services/rebalance/token/tokenRebalanceService.d.ts +0 -51
- package/dist/sdks/long-yield-carry/src/services/rebalance/token/tokenRebalanceService.js +0 -99
- package/dist/sdks/long-yield-carry/src/services/rebalance/yieldingBank/index.d.ts +0 -3
- package/dist/sdks/long-yield-carry/src/services/rebalance/yieldingBank/index.js +0 -21
- package/dist/sdks/long-yield-carry/src/services/rebalance/yieldingBank/planner.d.ts +0 -68
- package/dist/sdks/long-yield-carry/src/services/rebalance/yieldingBank/planner.js +0 -181
- package/dist/sdks/long-yield-carry/src/services/rebalance/yieldingBank/strategy.d.ts +0 -26
- package/dist/sdks/long-yield-carry/src/services/rebalance/yieldingBank/strategy.js +0 -26
- package/dist/sdks/long-yield-carry/src/services/rebalance/yieldingBank/types.d.ts +0 -40
- package/dist/sdks/long-yield-carry/src/services/rebalance/yieldingBank/types.js +0 -2
- package/dist/sdks/long-yield-carry/src/services/redemption/index.d.ts +0 -2
- package/dist/sdks/long-yield-carry/src/services/redemption/index.js +0 -5
- package/dist/sdks/long-yield-carry/src/services/redemption/redemptionService.d.ts +0 -139
- package/dist/sdks/long-yield-carry/src/services/redemption/redemptionService.js +0 -532
- package/dist/sdks/long-yield-carry/src/types/enriched.d.ts +0 -168
- package/dist/sdks/long-yield-carry/src/types/enriched.js +0 -2
- package/dist/sdks/long-yield-carry/src/types/index.d.ts +0 -1
- package/dist/sdks/long-yield-carry/src/types/index.js +0 -17
- package/dist/sdks/long-yield-carry/src/utils/cache.d.ts +0 -4
- package/dist/sdks/long-yield-carry/src/utils/cache.js +0 -10
- package/dist/sdks/long-yield-carry/src/utils/data.d.ts +0 -12
- package/dist/sdks/long-yield-carry/src/utils/data.js +0 -59
- package/dist/sdks/long-yield-carry/src/utils/enrichment.d.ts +0 -5
- package/dist/sdks/long-yield-carry/src/utils/enrichment.js +0 -244
- package/dist/sdks/long-yield-carry/src/utils/feeDripMetrics.d.ts +0 -36
- package/dist/sdks/long-yield-carry/src/utils/feeDripMetrics.js +0 -93
- package/dist/sdks/long-yield-carry/src/utils/general.d.ts +0 -28
- package/dist/sdks/long-yield-carry/src/utils/general.js +0 -47
- package/dist/sdks/long-yield-carry/src/utils/index.d.ts +0 -13
- package/dist/sdks/long-yield-carry/src/utils/index.js +0 -29
- package/dist/sdks/long-yield-carry/src/utils/ix.d.ts +0 -83
- package/dist/sdks/long-yield-carry/src/utils/ix.js +0 -165
- package/dist/sdks/long-yield-carry/src/utils/lendingPosition.d.ts +0 -68
- package/dist/sdks/long-yield-carry/src/utils/lendingPosition.js +0 -105
- package/dist/sdks/long-yield-carry/src/utils/lookupTables.d.ts +0 -55
- package/dist/sdks/long-yield-carry/src/utils/lookupTables.js +0 -216
- package/dist/sdks/long-yield-carry/src/utils/lycData.d.ts +0 -66
- package/dist/sdks/long-yield-carry/src/utils/lycData.js +0 -211
- package/dist/sdks/long-yield-carry/src/utils/timelock.d.ts +0 -19
- package/dist/sdks/long-yield-carry/src/utils/timelock.js +0 -37
- package/dist/sdks/long-yield-carry/src/utils/tokenFeeMath.d.ts +0 -11
- package/dist/sdks/long-yield-carry/src/utils/tokenFeeMath.js +0 -24
- package/dist/sdks/long-yield-carry/src/utils/transactions.d.ts +0 -20
- package/dist/sdks/long-yield-carry/src/utils/transactions.js +0 -72
- package/dist/sdks/long-yield-carry/src/utils/yieldingBank.d.ts +0 -24
- package/dist/sdks/long-yield-carry/src/utils/yieldingBank.js +0 -36
- package/dist/shared/common/src/constants/accountMetas.d.ts +0 -3
- package/dist/shared/common/src/constants/accountMetas.js +0 -9
- package/dist/shared/common/src/constants/general.d.ts +0 -21
- package/dist/shared/common/src/constants/general.js +0 -30
- package/dist/shared/common/src/constants/generated/cpi.d.ts +0 -23
- package/dist/shared/common/src/constants/generated/cpi.js +0 -28
- package/dist/shared/common/src/constants/generated/index.d.ts +0 -1
- package/dist/shared/common/src/constants/generated/index.js +0 -17
- package/dist/shared/common/src/constants/index.d.ts +0 -3
- package/dist/shared/common/src/constants/index.js +0 -19
- package/dist/shared/common/src/index.d.ts +0 -4
- package/dist/shared/common/src/index.js +0 -20
- package/dist/shared/common/src/services/baseAccountClient.d.ts +0 -22
- package/dist/shared/common/src/services/baseAccountClient.js +0 -38
- package/dist/shared/common/src/services/baseIxBuilderService.d.ts +0 -27
- package/dist/shared/common/src/services/baseIxBuilderService.js +0 -48
- package/dist/shared/common/src/services/dataCache.d.ts +0 -41
- package/dist/shared/common/src/services/dataCache.js +0 -130
- package/dist/shared/common/src/services/index.d.ts +0 -8
- package/dist/shared/common/src/services/index.js +0 -24
- package/dist/shared/common/src/services/lutManager.d.ts +0 -31
- package/dist/shared/common/src/services/lutManager.js +0 -133
- package/dist/shared/common/src/services/mints/defaults.d.ts +0 -2
- package/dist/shared/common/src/services/mints/defaults.js +0 -152
- package/dist/shared/common/src/services/mints/index.d.ts +0 -4
- package/dist/shared/common/src/services/mints/index.js +0 -20
- package/dist/shared/common/src/services/mints/registry.d.ts +0 -70
- package/dist/shared/common/src/services/mints/registry.js +0 -117
- package/dist/shared/common/src/services/mints/symbols.d.ts +0 -6
- package/dist/shared/common/src/services/mints/symbols.js +0 -13
- package/dist/shared/common/src/services/mints/types.d.ts +0 -30
- package/dist/shared/common/src/services/mints/types.js +0 -2
- package/dist/shared/common/src/services/swap/index.d.ts +0 -4
- package/dist/shared/common/src/services/swap/index.js +0 -20
- package/dist/shared/common/src/services/swap/routableSwapClient.d.ts +0 -36
- package/dist/shared/common/src/services/swap/routableSwapClient.js +0 -2
- package/dist/shared/common/src/services/swap/swapClientBase.d.ts +0 -45
- package/dist/shared/common/src/services/swap/swapClientBase.js +0 -2
- package/dist/shared/common/src/services/swap/swapRouting.d.ts +0 -13
- package/dist/shared/common/src/services/swap/swapRouting.js +0 -28
- package/dist/shared/common/src/services/swap/types.d.ts +0 -77
- package/dist/shared/common/src/services/swap/types.js +0 -2
- package/dist/shared/common/src/services/token/index.d.ts +0 -2
- package/dist/shared/common/src/services/token/index.js +0 -18
- package/dist/shared/common/src/services/token/tokenProtocolClientBase.d.ts +0 -51
- package/dist/shared/common/src/services/token/tokenProtocolClientBase.js +0 -2
- package/dist/shared/common/src/services/token/types.d.ts +0 -19
- package/dist/shared/common/src/services/token/types.js +0 -2
- package/dist/shared/common/src/services/transactionSender.d.ts +0 -24
- package/dist/shared/common/src/services/transactionSender.js +0 -30
- package/dist/shared/common/src/types/cpi.d.ts +0 -34
- package/dist/shared/common/src/types/cpi.js +0 -8
- package/dist/shared/common/src/types/enums.d.ts +0 -59
- package/dist/shared/common/src/types/enums.js +0 -122
- package/dist/shared/common/src/types/general.d.ts +0 -38
- package/dist/shared/common/src/types/general.js +0 -2
- package/dist/shared/common/src/types/index.d.ts +0 -4
- package/dist/shared/common/src/types/index.js +0 -20
- package/dist/shared/common/src/types/solana.d.ts +0 -24
- package/dist/shared/common/src/types/solana.js +0 -2
- package/dist/shared/common/src/utils/accounts/index.d.ts +0 -5
- package/dist/shared/common/src/utils/accounts/index.js +0 -21
- package/dist/shared/common/src/utils/accounts/meta.d.ts +0 -21
- package/dist/shared/common/src/utils/accounts/meta.js +0 -27
- package/dist/shared/common/src/utils/accounts/pda.d.ts +0 -2
- package/dist/shared/common/src/utils/accounts/pda.js +0 -17
- package/dist/shared/common/src/utils/accounts/roles.d.ts +0 -26
- package/dist/shared/common/src/utils/accounts/roles.js +0 -54
- package/dist/shared/common/src/utils/accounts/rpc.d.ts +0 -8
- package/dist/shared/common/src/utils/accounts/rpc.js +0 -30
- package/dist/shared/common/src/utils/accounts/splBalances.d.ts +0 -15
- package/dist/shared/common/src/utils/accounts/splBalances.js +0 -52
- package/dist/shared/common/src/utils/anchor.d.ts +0 -17
- package/dist/shared/common/src/utils/anchor.js +0 -29
- package/dist/shared/common/src/utils/asyncConcurrency.d.ts +0 -5
- package/dist/shared/common/src/utils/asyncConcurrency.js +0 -28
- package/dist/shared/common/src/utils/compat.d.ts +0 -46
- package/dist/shared/common/src/utils/compat.js +0 -72
- package/dist/shared/common/src/utils/cpi/args.d.ts +0 -69
- package/dist/shared/common/src/utils/cpi/args.js +0 -100
- package/dist/shared/common/src/utils/cpi/index.d.ts +0 -2
- package/dist/shared/common/src/utils/cpi/index.js +0 -18
- package/dist/shared/common/src/utils/cpi/refs.d.ts +0 -122
- package/dist/shared/common/src/utils/cpi/refs.js +0 -234
- package/dist/shared/common/src/utils/data.d.ts +0 -20
- package/dist/shared/common/src/utils/data.js +0 -27
- package/dist/shared/common/src/utils/general.d.ts +0 -24
- package/dist/shared/common/src/utils/general.js +0 -95
- package/dist/shared/common/src/utils/index.d.ts +0 -22
- package/dist/shared/common/src/utils/index.js +0 -38
- package/dist/shared/common/src/utils/instruction.d.ts +0 -74
- package/dist/shared/common/src/utils/instruction.js +0 -147
- package/dist/shared/common/src/utils/jito.d.ts +0 -113
- package/dist/shared/common/src/utils/jito.js +0 -178
- package/dist/shared/common/src/utils/json.d.ts +0 -5
- package/dist/shared/common/src/utils/json.js +0 -25
- package/dist/shared/common/src/utils/jsonRpcFetch.d.ts +0 -21
- package/dist/shared/common/src/utils/jsonRpcFetch.js +0 -134
- package/dist/shared/common/src/utils/metadata.d.ts +0 -107
- package/dist/shared/common/src/utils/metadata.js +0 -194
- package/dist/shared/common/src/utils/numbers.d.ts +0 -72
- package/dist/shared/common/src/utils/numbers.js +0 -193
- package/dist/shared/common/src/utils/priorityFee.d.ts +0 -18
- package/dist/shared/common/src/utils/priorityFee.js +0 -63
- package/dist/shared/common/src/utils/retry.d.ts +0 -20
- package/dist/shared/common/src/utils/retry.js +0 -69
- package/dist/shared/common/src/utils/rpc.d.ts +0 -40
- package/dist/shared/common/src/utils/rpc.js +0 -130
- package/dist/shared/common/src/utils/solana.d.ts +0 -23
- package/dist/shared/common/src/utils/solana.js +0 -61
- package/dist/shared/common/src/utils/timeSeries.d.ts +0 -18
- package/dist/shared/common/src/utils/timeSeries.js +0 -40
- package/dist/shared/common/src/utils/token.d.ts +0 -33
- package/dist/shared/common/src/utils/token.js +0 -82
- package/dist/shared/common/src/utils/transaction.d.ts +0 -154
- package/dist/shared/common/src/utils/transaction.js +0 -585
- package/dist/shared/common/src/utils/transactionSplitter.d.ts +0 -85
- package/dist/shared/common/src/utils/transactionSplitter.js +0 -127
- package/dist/shared/common/src/utils/txAccountCoverage.d.ts +0 -49
- package/dist/shared/common/src/utils/txAccountCoverage.js +0 -122
- package/dist/shared/jupiter-helpers/src/api.d.ts +0 -59
- package/dist/shared/jupiter-helpers/src/api.js +0 -130
- package/dist/shared/jupiter-helpers/src/client.d.ts +0 -79
- package/dist/shared/jupiter-helpers/src/client.js +0 -173
- package/dist/shared/jupiter-helpers/src/constants.d.ts +0 -35
- package/dist/shared/jupiter-helpers/src/constants.js +0 -38
- package/dist/shared/jupiter-helpers/src/extract.d.ts +0 -30
- package/dist/shared/jupiter-helpers/src/extract.js +0 -57
- package/dist/shared/jupiter-helpers/src/index.d.ts +0 -5
- package/dist/shared/jupiter-helpers/src/index.js +0 -21
- package/dist/shared/jupiter-helpers/src/routePreInstructions.d.ts +0 -19
- package/dist/shared/jupiter-helpers/src/routePreInstructions.js +0 -61
- package/dist/shared/jupiter-helpers/src/sizeExactInForMinOutput.d.ts +0 -70
- package/dist/shared/jupiter-helpers/src/sizeExactInForMinOutput.js +0 -95
- package/dist/shared/jupiter-helpers/src/types.d.ts +0 -66
- package/dist/shared/jupiter-helpers/src/types.js +0 -2
- package/dist/shared/lending-platforms/src/constants/cache.d.ts +0 -8
- package/dist/shared/lending-platforms/src/constants/cache.js +0 -11
- package/dist/shared/lending-platforms/src/constants/index.d.ts +0 -3
- package/dist/shared/lending-platforms/src/constants/index.js +0 -19
- package/dist/shared/lending-platforms/src/constants/kamino.d.ts +0 -7
- package/dist/shared/lending-platforms/src/constants/kamino.js +0 -83
- package/dist/shared/lending-platforms/src/constants/lendingPosition.d.ts +0 -7
- package/dist/shared/lending-platforms/src/constants/lendingPosition.js +0 -10
- package/dist/shared/lending-platforms/src/data/accounts/index.d.ts +0 -2
- package/dist/shared/lending-platforms/src/data/accounts/index.js +0 -18
- package/dist/shared/lending-platforms/src/data/accounts/kamino.d.ts +0 -42
- package/dist/shared/lending-platforms/src/data/accounts/kamino.js +0 -104
- package/dist/shared/lending-platforms/src/data/accounts/lpAccountsBase.d.ts +0 -7
- package/dist/shared/lending-platforms/src/data/accounts/lpAccountsBase.js +0 -9
- package/dist/shared/lending-platforms/src/data/incentive/incentiveBase.d.ts +0 -35
- package/dist/shared/lending-platforms/src/data/incentive/incentiveBase.js +0 -26
- package/dist/shared/lending-platforms/src/data/incentive/index.d.ts +0 -2
- package/dist/shared/lending-platforms/src/data/incentive/index.js +0 -18
- package/dist/shared/lending-platforms/src/data/incentive/kamino.d.ts +0 -55
- package/dist/shared/lending-platforms/src/data/incentive/kamino.js +0 -101
- package/dist/shared/lending-platforms/src/data/index.d.ts +0 -6
- package/dist/shared/lending-platforms/src/data/index.js +0 -22
- package/dist/shared/lending-platforms/src/data/instructions/index.d.ts +0 -3
- package/dist/shared/lending-platforms/src/data/instructions/index.js +0 -19
- package/dist/shared/lending-platforms/src/data/instructions/kamino.d.ts +0 -55
- package/dist/shared/lending-platforms/src/data/instructions/kamino.js +0 -630
- package/dist/shared/lending-platforms/src/data/instructions/lpInstructionsBase.d.ts +0 -175
- package/dist/shared/lending-platforms/src/data/instructions/lpInstructionsBase.js +0 -192
- package/dist/shared/lending-platforms/src/data/instructions/types.d.ts +0 -7
- package/dist/shared/lending-platforms/src/data/instructions/types.js +0 -2
- package/dist/shared/lending-platforms/src/data/platform/index.d.ts +0 -2
- package/dist/shared/lending-platforms/src/data/platform/index.js +0 -18
- package/dist/shared/lending-platforms/src/data/platform/kamino.d.ts +0 -59
- package/dist/shared/lending-platforms/src/data/platform/kamino.js +0 -206
- package/dist/shared/lending-platforms/src/data/platform/lpDataBase.d.ts +0 -35
- package/dist/shared/lending-platforms/src/data/platform/lpDataBase.js +0 -31
- package/dist/shared/lending-platforms/src/data/reserve/index.d.ts +0 -2
- package/dist/shared/lending-platforms/src/data/reserve/index.js +0 -18
- package/dist/shared/lending-platforms/src/data/reserve/kamino.d.ts +0 -45
- package/dist/shared/lending-platforms/src/data/reserve/kamino.js +0 -141
- package/dist/shared/lending-platforms/src/data/reserve/reserveBase.d.ts +0 -114
- package/dist/shared/lending-platforms/src/data/reserve/reserveBase.js +0 -125
- package/dist/shared/lending-platforms/src/data/userPosition/index.d.ts +0 -2
- package/dist/shared/lending-platforms/src/data/userPosition/index.js +0 -18
- package/dist/shared/lending-platforms/src/data/userPosition/kamino.d.ts +0 -15
- package/dist/shared/lending-platforms/src/data/userPosition/kamino.js +0 -45
- package/dist/shared/lending-platforms/src/data/userPosition/userPositionBase.d.ts +0 -50
- package/dist/shared/lending-platforms/src/data/userPosition/userPositionBase.js +0 -63
- package/dist/shared/lending-platforms/src/index.d.ts +0 -5
- package/dist/shared/lending-platforms/src/index.js +0 -21
- package/dist/shared/lending-platforms/src/services/client/index.d.ts +0 -2
- package/dist/shared/lending-platforms/src/services/client/index.js +0 -18
- package/dist/shared/lending-platforms/src/services/client/kamino.d.ts +0 -53
- package/dist/shared/lending-platforms/src/services/client/kamino.js +0 -142
- package/dist/shared/lending-platforms/src/services/client/lpClientBase.d.ts +0 -66
- package/dist/shared/lending-platforms/src/services/client/lpClientBase.js +0 -19
- package/dist/shared/lending-platforms/src/services/flashLoan/flashLoanBase.d.ts +0 -49
- package/dist/shared/lending-platforms/src/services/flashLoan/flashLoanBase.js +0 -16
- package/dist/shared/lending-platforms/src/services/flashLoan/index.d.ts +0 -2
- package/dist/shared/lending-platforms/src/services/flashLoan/index.js +0 -18
- package/dist/shared/lending-platforms/src/services/flashLoan/kamino.d.ts +0 -11
- package/dist/shared/lending-platforms/src/services/flashLoan/kamino.js +0 -85
- package/dist/shared/lending-platforms/src/services/index.d.ts +0 -5
- package/dist/shared/lending-platforms/src/services/index.js +0 -21
- package/dist/shared/lending-platforms/src/services/lendingPosition/index.d.ts +0 -2
- package/dist/shared/lending-platforms/src/services/lendingPosition/index.js +0 -18
- package/dist/shared/lending-platforms/src/services/lendingPosition/lendingPositionManager.d.ts +0 -117
- package/dist/shared/lending-platforms/src/services/lendingPosition/lendingPositionManager.js +0 -342
- package/dist/shared/lending-platforms/src/services/lendingPosition/types.d.ts +0 -40
- package/dist/shared/lending-platforms/src/services/lendingPosition/types.js +0 -2
- package/dist/shared/lending-platforms/src/services/leverage/index.d.ts +0 -2
- package/dist/shared/lending-platforms/src/services/leverage/index.js +0 -18
- package/dist/shared/lending-platforms/src/services/leverage/leverageService.d.ts +0 -104
- package/dist/shared/lending-platforms/src/services/leverage/leverageService.js +0 -437
- package/dist/shared/lending-platforms/src/services/leverage/types.d.ts +0 -261
- package/dist/shared/lending-platforms/src/services/leverage/types.js +0 -2
- package/dist/shared/lending-platforms/src/services/reservesManager.d.ts +0 -53
- package/dist/shared/lending-platforms/src/services/reservesManager.js +0 -112
- package/dist/shared/lending-platforms/src/types/general.d.ts +0 -37
- package/dist/shared/lending-platforms/src/types/general.js +0 -8
- package/dist/shared/lending-platforms/src/types/index.d.ts +0 -2
- package/dist/shared/lending-platforms/src/types/index.js +0 -18
- package/dist/shared/lending-platforms/src/types/kamino.d.ts +0 -10
- package/dist/shared/lending-platforms/src/types/kamino.js +0 -2
- package/dist/shared/lending-platforms/src/utils/accounts.d.ts +0 -16
- package/dist/shared/lending-platforms/src/utils/accounts.js +0 -36
- package/dist/shared/lending-platforms/src/utils/cache.d.ts +0 -3
- package/dist/shared/lending-platforms/src/utils/cache.js +0 -11
- package/dist/shared/lending-platforms/src/utils/index.d.ts +0 -6
- package/dist/shared/lending-platforms/src/utils/index.js +0 -22
- package/dist/shared/lending-platforms/src/utils/kamino.d.ts +0 -87
- package/dist/shared/lending-platforms/src/utils/kamino.js +0 -190
- package/dist/shared/lending-platforms/src/utils/lendingPlatform.d.ts +0 -6
- package/dist/shared/lending-platforms/src/utils/lendingPlatform.js +0 -16
- package/dist/shared/lending-platforms/src/utils/math.d.ts +0 -47
- package/dist/shared/lending-platforms/src/utils/math.js +0 -123
- package/dist/shared/lending-platforms/src/utils/scope.d.ts +0 -38
- package/dist/shared/lending-platforms/src/utils/scope.js +0 -144
- package/dist/shared/oracle-service/src/constants/index.d.ts +0 -3
- package/dist/shared/oracle-service/src/constants/index.js +0 -19
- package/dist/shared/oracle-service/src/constants/pyth.d.ts +0 -7
- package/dist/shared/oracle-service/src/constants/pyth.js +0 -71
- package/dist/shared/oracle-service/src/constants/splStake.d.ts +0 -2
- package/dist/shared/oracle-service/src/constants/splStake.js +0 -6
- package/dist/shared/oracle-service/src/constants/switchboard.d.ts +0 -7
- package/dist/shared/oracle-service/src/constants/switchboard.js +0 -10
- package/dist/shared/oracle-service/src/feeds/custom.d.ts +0 -30
- package/dist/shared/oracle-service/src/feeds/custom.js +0 -56
- package/dist/shared/oracle-service/src/feeds/jupiter.d.ts +0 -7
- package/dist/shared/oracle-service/src/feeds/jupiter.js +0 -43
- package/dist/shared/oracle-service/src/feeds/priceBase.d.ts +0 -13
- package/dist/shared/oracle-service/src/feeds/priceBase.js +0 -25
- package/dist/shared/oracle-service/src/feeds/pyth.d.ts +0 -8
- package/dist/shared/oracle-service/src/feeds/pyth.js +0 -59
- package/dist/shared/oracle-service/src/feeds/splStake.d.ts +0 -26
- package/dist/shared/oracle-service/src/feeds/splStake.js +0 -99
- package/dist/shared/oracle-service/src/feeds/switchboard.d.ts +0 -6
- package/dist/shared/oracle-service/src/feeds/switchboard.js +0 -11
- package/dist/shared/oracle-service/src/index.d.ts +0 -5
- package/dist/shared/oracle-service/src/index.js +0 -26
- package/dist/shared/oracle-service/src/oracle.d.ts +0 -22
- package/dist/shared/oracle-service/src/oracle.js +0 -104
- package/dist/shared/oracle-service/src/types.d.ts +0 -4
- package/dist/shared/oracle-service/src/types.js +0 -2
- package/dist/shared/oracle-service/src/utils/general.d.ts +0 -20
- package/dist/shared/oracle-service/src/utils/general.js +0 -65
- package/dist/shared/oracle-service/src/utils/index.d.ts +0 -1
- package/dist/shared/oracle-service/src/utils/index.js +0 -17
- package/dist/shared/perena-helpers/src/accounts.d.ts +0 -7
- package/dist/shared/perena-helpers/src/accounts.js +0 -12
- package/dist/shared/perena-helpers/src/client.d.ts +0 -299
- package/dist/shared/perena-helpers/src/client.js +0 -680
- package/dist/shared/perena-helpers/src/constants.d.ts +0 -5
- package/dist/shared/perena-helpers/src/constants.js +0 -8
- package/dist/shared/perena-helpers/src/cpi/burn.d.ts +0 -27
- package/dist/shared/perena-helpers/src/cpi/burn.js +0 -22
- package/dist/shared/perena-helpers/src/cpi/index.d.ts +0 -3
- package/dist/shared/perena-helpers/src/cpi/index.js +0 -19
- package/dist/shared/perena-helpers/src/cpi/mint.d.ts +0 -27
- package/dist/shared/perena-helpers/src/cpi/mint.js +0 -22
- package/dist/shared/perena-helpers/src/cpi/requestUnstake.d.ts +0 -19
- package/dist/shared/perena-helpers/src/cpi/requestUnstake.js +0 -16
- package/dist/shared/perena-helpers/src/index.d.ts +0 -5
- package/dist/shared/perena-helpers/src/index.js +0 -21
- package/dist/shared/perena-helpers/src/utils.d.ts +0 -9
- package/dist/shared/perena-helpers/src/utils.js +0 -54
- package/dist/shared/swap-aggregator/src/aggSwapClient.d.ts +0 -71
- package/dist/shared/swap-aggregator/src/aggSwapClient.js +0 -103
- package/dist/shared/swap-aggregator/src/index.d.ts +0 -1
- package/dist/shared/swap-aggregator/src/index.js +0 -17
- package/docs/launchingToken.md +0 -57
- package/scripts/asyncBurn.ts +0 -155
- package/scripts/burnToken.ts +0 -120
- package/scripts/claimIncentives.ts +0 -125
- package/scripts/closeCpiPlans.ts +0 -113
- package/scripts/collectInterest.ts +0 -194
- package/scripts/collectProtocolFees.ts +0 -144
- package/scripts/computeOptimalAllocations.ts +0 -117
- package/scripts/createToken.ts +0 -100
- package/scripts/createTokenLendingPosition.ts +0 -204
- package/scripts/createYieldingBank.ts +0 -91
- package/scripts/decreaseCarryPositions.ts +0 -359
- package/scripts/depositUnlentCollateral.ts +0 -106
- package/scripts/emergency/deleverageAll.ts +0 -287
- package/scripts/emergency/triggerCircuitBreaker.ts +0 -87
- package/scripts/env.ts +0 -4
- package/scripts/findTxs.ts +0 -169
- package/scripts/increaseCarryPositions.ts +0 -134
- package/scripts/inspect/format.ts +0 -576
- package/scripts/inspect.ts +0 -147
- package/scripts/localUtils.ts +0 -249
- package/scripts/mintToken.ts +0 -126
- package/scripts/processAsyncBurns.ts +0 -89
- package/scripts/rebalanceToken.ts +0 -269
- package/scripts/rebalanceYieldingBank.ts +0 -183
- package/scripts/recollateralizeLoss.ts +0 -79
- package/scripts/refresh.ts +0 -156
- package/scripts/updateFees.ts +0 -486
- package/scripts/updateGeneralLut.ts +0 -36
- package/scripts/updateLendingPositionConfig.ts +0 -172
- package/scripts/updateTokenLuts.ts +0 -36
- package/scripts/updateTokenMetadata.ts +0 -199
- package/scripts/updateYieldingBankConfig.ts +0 -100
- package/scripts/withdrawUnlentCollateral.ts +0 -178
- package/src/client/account.ts +0 -503
- package/src/client/builders/args.ts +0 -381
- package/src/client/builders/asyncBurnBuilder.ts +0 -305
- package/src/client/builders/base.ts +0 -303
- package/src/client/builders/burnTokenBuilder.ts +0 -258
- package/src/client/builders/claimIncentivesBuilder.ts +0 -211
- package/src/client/builders/collectFeesBuilder.ts +0 -52
- package/src/client/builders/collectInterestBuilder.ts +0 -165
- package/src/client/builders/createCpiPlanBuilder.ts +0 -21
- package/src/client/builders/createTokenBuilder.ts +0 -73
- package/src/client/builders/createTokenLendingPositionBuilder.ts +0 -219
- package/src/client/builders/createYieldingBankAllocationBuilder.ts +0 -32
- package/src/client/builders/createYieldingBankBuilder.ts +0 -39
- package/src/client/builders/decreaseCarryPositionBuilder.ts +0 -162
- package/src/client/builders/depositUnlentCollateralBuilder.ts +0 -95
- package/src/client/builders/increaseCarryPositionBuilder.ts +0 -105
- package/src/client/builders/index.ts +0 -37
- package/src/client/builders/mintTokenBuilder.ts +0 -137
- package/src/client/builders/rebalanceTokenBuilder.ts +0 -356
- package/src/client/builders/rebalanceYieldingBankBuilder.ts +0 -109
- package/src/client/builders/recollateralizeLossBuilder.ts +0 -367
- package/src/client/builders/refreshTokenStateBuilder.ts +0 -153
- package/src/client/builders/refreshTokensBuilder.ts +0 -82
- package/src/client/builders/refreshYieldingBankBuilder.ts +0 -42
- package/src/client/builders/resetTokenBurnRateLimitBuilder.ts +0 -21
- package/src/client/builders/setTokenCircuitBreakerBuilder.ts +0 -40
- package/src/client/builders/setYieldingBankCircuitBreakerBuilder.ts +0 -37
- package/src/client/builders/updateLendingPositionConfigBuilder.ts +0 -33
- package/src/client/builders/updateTokenConfigurationBuilder.ts +0 -50
- package/src/client/builders/updateTokenMetadataBuilder.ts +0 -24
- package/src/client/builders/updateYieldingBankConfigBuilder.ts +0 -32
- package/src/client/builders/utils.ts +0 -26
- package/src/client/client.ts +0 -264
- package/src/client/externalLiquidityResolver.ts +0 -54
- package/src/client/index.ts +0 -20
- package/src/client/lendingPlatformClients.ts +0 -50
- package/src/client/pda.ts +0 -102
- package/src/client/plans/collectInterest.ts +0 -207
- package/src/client/plans/decreaseCarryPosition.ts +0 -226
- package/src/client/routes/collectInterest.ts +0 -56
- package/src/client/transaction.ts +0 -106
- package/src/client/types/builders.ts +0 -19
- package/src/client/types/enums.ts +0 -47
- package/src/client/types/general.ts +0 -117
- package/src/client/types/index.ts +0 -6
- package/src/client/types/ix.ts +0 -452
- package/src/client/types/planTypes/collectInterest.ts +0 -97
- package/src/client/types/planTypes/common.ts +0 -31
- package/src/client/types/planTypes/decreaseCarryPosition.ts +0 -134
- package/src/client/types/planTypes/index.ts +0 -3
- package/src/client/types/tx.ts +0 -409
- package/src/constants/configs/allocations.ts +0 -30
- package/src/constants/configs/carryTradePresets.ts +0 -164
- package/src/constants/configs/index.ts +0 -2
- package/src/constants/general.ts +0 -141
- package/src/constants/index.ts +0 -3
- package/src/constants/lycTokenMetadata.ts +0 -52
- package/src/decoders/decodeTransaction.ts +0 -319
- package/src/decoders/discriminators.ts +0 -10
- package/src/decoders/idlAccounts.ts +0 -75
- package/src/decoders/index.ts +0 -15
- package/src/decoders/innerCpis.ts +0 -262
- package/src/decoders/lycInstructionNames.ts +0 -73
- package/src/decoders/programIds.ts +0 -12
- package/src/decoders/solana.ts +0 -25
- package/src/decoders/transactionPayload.ts +0 -41
- package/src/decoders/types.ts +0 -60
- package/src/errors.ts +0 -195
- package/src/idl/long_yield_carry.ts +0 -14648
- package/src/index.ts +0 -10
- package/src/metrics/index.ts +0 -1
- package/src/metrics/protocolMetrics.ts +0 -976
- package/src/models/index.ts +0 -9
- package/src/models/lycToken.ts +0 -380
- package/src/models/yieldingBank.ts +0 -127
- package/src/services/allocation/allocationService.ts +0 -823
- package/src/services/allocation/index.ts +0 -2
- package/src/services/allocation/types.ts +0 -27
- package/src/services/carry/carryAllocationConfig.ts +0 -266
- package/src/services/carry/index.ts +0 -2
- package/src/services/carry/lycLendingPositionManager.ts +0 -167
- package/src/services/index.ts +0 -5
- package/src/services/lendingPosition/index.ts +0 -5
- package/src/services/lendingPosition/lendingPositionService.ts +0 -328
- package/src/services/rebalance/index.ts +0 -2
- package/src/services/rebalance/token/index.ts +0 -1
- package/src/services/rebalance/token/tokenRebalanceService.ts +0 -142
- package/src/services/rebalance/yieldingBank/index.ts +0 -3
- package/src/services/rebalance/yieldingBank/planner.ts +0 -215
- package/src/services/rebalance/yieldingBank/strategy.ts +0 -41
- package/src/services/rebalance/yieldingBank/types.ts +0 -41
- package/src/services/redemption/index.ts +0 -9
- package/src/services/redemption/redemptionService.ts +0 -758
- package/src/types/enriched.ts +0 -187
- package/src/types/index.ts +0 -1
- package/src/utils/cache.ts +0 -12
- package/src/utils/data.ts +0 -65
- package/src/utils/enrichment.ts +0 -330
- package/src/utils/feeDripMetrics.ts +0 -146
- package/src/utils/general.ts +0 -54
- package/src/utils/index.ts +0 -13
- package/src/utils/ix.ts +0 -227
- package/src/utils/lendingPosition.ts +0 -221
- package/src/utils/lookupTables.ts +0 -309
- package/src/utils/lycData.ts +0 -321
- package/src/utils/timelock.ts +0 -63
- package/src/utils/tokenFeeMath.ts +0 -25
- package/src/utils/transactions.ts +0 -109
- package/src/utils/yieldingBank.ts +0 -38
- package/tsconfig.json +0 -11
|
@@ -0,0 +1,3707 @@
|
|
|
1
|
+
// ../../shared/common/src/constants/general.ts
|
|
2
|
+
import { address } from "@solana/kit";
|
|
3
|
+
var ENVIRONMENT = process.env.ENVIRONMENT ?? "local";
|
|
4
|
+
var DAYS_PER_YEAR = 365;
|
|
5
|
+
var TVL_USD_DECIMAL_PLACES = 8;
|
|
6
|
+
var TVL_USD_SCALE = BigInt(10 ** TVL_USD_DECIMAL_PLACES);
|
|
7
|
+
var BPS_DENOMINATOR = 10000n;
|
|
8
|
+
var DEFAULT_PUBLIC_KEY = address("11111111111111111111111111111111");
|
|
9
|
+
var LOCALNET_URL = "http://127.0.0.1:8899";
|
|
10
|
+
var PROTOCOL_ADMIN = {
|
|
11
|
+
local: address("7PxS1VMxKbzUTF4sxeAw4LqBfnGMaeQH2KwabmUcVxYC"),
|
|
12
|
+
test: address("8S1Ta7xZVsiqtf9mrUPwXKSNmBPzmsK3RdhonDu3kzk"),
|
|
13
|
+
prod: address("42GmTZiLdcJHmxCik4WvxTYeNirzFqsr7DXWZDst4gxE")
|
|
14
|
+
// TODO: multisig admin
|
|
15
|
+
};
|
|
16
|
+
var DEPLOYED_ADMIN_KEYPAIR_FP = {
|
|
17
|
+
test: "~/.config/solana/tp/lyc-admin-test.json",
|
|
18
|
+
prod: "~/.config/solana/tp/lyc-admin-prod.json"
|
|
19
|
+
};
|
|
20
|
+
var PRICE_STALENESS_SECONDS = 60;
|
|
21
|
+
var METAPLEX_TOKEN_METADATA_PROGRAM_ID = address(
|
|
22
|
+
"metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s"
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
// ../../shared/common/src/utils/transaction.ts
|
|
26
|
+
import {
|
|
27
|
+
pipe,
|
|
28
|
+
createTransactionMessage,
|
|
29
|
+
setTransactionMessageLifetimeUsingBlockhash,
|
|
30
|
+
appendTransactionMessageInstructions,
|
|
31
|
+
compressTransactionMessageUsingAddressLookupTables,
|
|
32
|
+
compileTransaction as compileTransaction3,
|
|
33
|
+
signTransactionMessageWithSigners,
|
|
34
|
+
getSignatureFromTransaction,
|
|
35
|
+
getBase64EncodedWireTransaction as getBase64EncodedWireTransaction2,
|
|
36
|
+
setTransactionMessageFeePayerSigner,
|
|
37
|
+
addSignersToTransactionMessage,
|
|
38
|
+
assertIsFullySignedTransaction,
|
|
39
|
+
isTransactionModifyingSigner,
|
|
40
|
+
isTransactionPartialSigner
|
|
41
|
+
} from "@solana/kit";
|
|
42
|
+
|
|
43
|
+
// ../../shared/common/src/utils/instruction.ts
|
|
44
|
+
import {
|
|
45
|
+
getRequestHeapFrameInstruction,
|
|
46
|
+
getSetComputeUnitLimitInstruction,
|
|
47
|
+
getSetComputeUnitPriceInstruction
|
|
48
|
+
} from "@solana-program/compute-budget";
|
|
49
|
+
import {
|
|
50
|
+
fetchMaybeToken as fetchMaybeToken2,
|
|
51
|
+
getCreateAssociatedTokenIdempotentInstruction,
|
|
52
|
+
getSyncNativeInstruction,
|
|
53
|
+
getCloseAccountInstruction,
|
|
54
|
+
TOKEN_PROGRAM_ADDRESS as TOKEN_PROGRAM_ADDRESS3
|
|
55
|
+
} from "@solana-program/token";
|
|
56
|
+
import { getTransferSolInstruction } from "@solana-program/system";
|
|
57
|
+
|
|
58
|
+
// ../../shared/common/src/services/baseAccountClient.ts
|
|
59
|
+
import { fetchMaybeToken } from "@solana-program/token";
|
|
60
|
+
|
|
61
|
+
// ../../shared/common/src/services/dataCache.ts
|
|
62
|
+
var DataCache = class {
|
|
63
|
+
constructor(ttlConfig) {
|
|
64
|
+
this.cache = /* @__PURE__ */ new Map();
|
|
65
|
+
this.ttlConfig = {
|
|
66
|
+
defaultTtlMs: ttlConfig?.defaultTtlMs ?? 6e4 * 5,
|
|
67
|
+
// 5 minute default
|
|
68
|
+
categoryTtlMs: ttlConfig?.categoryTtlMs ?? {}
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
async getData(fetchFn, category, id, options) {
|
|
72
|
+
let data = this.tryFromCache(category, id);
|
|
73
|
+
let fromCache = true;
|
|
74
|
+
if (!data) {
|
|
75
|
+
data = await fetchFn();
|
|
76
|
+
if (data !== null || options?.cacheNull !== false) {
|
|
77
|
+
this.setCache(category, id, data);
|
|
78
|
+
}
|
|
79
|
+
fromCache = false;
|
|
80
|
+
}
|
|
81
|
+
return { data, fromCache };
|
|
82
|
+
}
|
|
83
|
+
async getDataOrThrow(fetchFn, category, id, options) {
|
|
84
|
+
const { data, fromCache } = await this.getData(fetchFn, category, id, options);
|
|
85
|
+
if (!data) {
|
|
86
|
+
throw new Error(`Failed to fetch ${category} data, ID: ${id}`);
|
|
87
|
+
}
|
|
88
|
+
return { data, fromCache };
|
|
89
|
+
}
|
|
90
|
+
async getDataBatch(fetchFn, category, ids) {
|
|
91
|
+
let data = ids.map((id) => this.tryFromCache(category, id));
|
|
92
|
+
let fromCache = true;
|
|
93
|
+
if (data.some((item) => item === null)) {
|
|
94
|
+
data = await fetchFn();
|
|
95
|
+
if (!data) {
|
|
96
|
+
throw new Error(`Failed to batch fetch ${category} data`);
|
|
97
|
+
}
|
|
98
|
+
for (let i = 0; i < ids.length; i++) {
|
|
99
|
+
this.setCache(category, ids[i], data[i]);
|
|
100
|
+
}
|
|
101
|
+
fromCache = false;
|
|
102
|
+
}
|
|
103
|
+
return { data, fromCache };
|
|
104
|
+
}
|
|
105
|
+
getTtlForCategory(category) {
|
|
106
|
+
return this.ttlConfig.categoryTtlMs?.[category] ?? this.ttlConfig.defaultTtlMs;
|
|
107
|
+
}
|
|
108
|
+
isStale(entry, category) {
|
|
109
|
+
const ttl = this.getTtlForCategory(category);
|
|
110
|
+
const age = Date.now() - entry.timestamp;
|
|
111
|
+
return age > ttl;
|
|
112
|
+
}
|
|
113
|
+
/** Returns null if not found or stale */
|
|
114
|
+
tryFromCache(category, id) {
|
|
115
|
+
const categoryCache = this.cache.get(category);
|
|
116
|
+
if (!categoryCache) {
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
const entry = categoryCache.get(id);
|
|
120
|
+
if (!entry) {
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
if (this.isStale(entry, category)) {
|
|
124
|
+
categoryCache.delete(id);
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
return entry.data;
|
|
128
|
+
}
|
|
129
|
+
getCacheAge(category, id) {
|
|
130
|
+
const categoryCache = this.cache.get(category);
|
|
131
|
+
if (!categoryCache) {
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
const entry = categoryCache.get(id);
|
|
135
|
+
if (!entry) {
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
return Date.now() - entry.timestamp;
|
|
139
|
+
}
|
|
140
|
+
setCache(category, id, data) {
|
|
141
|
+
let categoryCache = this.cache.get(category);
|
|
142
|
+
if (!categoryCache) {
|
|
143
|
+
categoryCache = /* @__PURE__ */ new Map();
|
|
144
|
+
this.cache.set(category, categoryCache);
|
|
145
|
+
}
|
|
146
|
+
categoryCache.set(id, {
|
|
147
|
+
data,
|
|
148
|
+
timestamp: Date.now()
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
refreshCategory(category) {
|
|
152
|
+
const categoryCache = this.cache.get(category);
|
|
153
|
+
if (categoryCache) {
|
|
154
|
+
categoryCache.clear();
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
clearCacheEntry(category, id) {
|
|
158
|
+
const categoryCache = this.cache.get(category);
|
|
159
|
+
if (!categoryCache) {
|
|
160
|
+
return false;
|
|
161
|
+
}
|
|
162
|
+
return categoryCache.delete(id);
|
|
163
|
+
}
|
|
164
|
+
clearStaleEntries(category) {
|
|
165
|
+
const categoryCache = this.cache.get(category);
|
|
166
|
+
if (!categoryCache) {
|
|
167
|
+
return 0;
|
|
168
|
+
}
|
|
169
|
+
let cleared = 0;
|
|
170
|
+
for (const [id, entry] of categoryCache.entries()) {
|
|
171
|
+
if (this.isStale(entry, category)) {
|
|
172
|
+
categoryCache.delete(id);
|
|
173
|
+
cleared++;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
return cleared;
|
|
177
|
+
}
|
|
178
|
+
clearAllStaleEntries() {
|
|
179
|
+
let totalCleared = 0;
|
|
180
|
+
for (const category of this.cache.keys()) {
|
|
181
|
+
totalCleared += this.clearStaleEntries(category);
|
|
182
|
+
}
|
|
183
|
+
return totalCleared;
|
|
184
|
+
}
|
|
185
|
+
clearAllCache() {
|
|
186
|
+
this.cache.clear();
|
|
187
|
+
}
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
// ../../shared/common/src/services/baseAccountClient.ts
|
|
191
|
+
var SPL_ATA_CACHE_CATEGORY = "splAta";
|
|
192
|
+
var DEFAULT_SPL_ATA_TTL_MS = 6e4 * 10;
|
|
193
|
+
var BaseAccountClient = class {
|
|
194
|
+
constructor(rpc, options) {
|
|
195
|
+
this.rpc = rpc;
|
|
196
|
+
this.dataCache = new DataCache({
|
|
197
|
+
defaultTtlMs: options?.defaultTtlMs,
|
|
198
|
+
categoryTtlMs: {
|
|
199
|
+
[SPL_ATA_CACHE_CATEGORY]: DEFAULT_SPL_ATA_TTL_MS,
|
|
200
|
+
...options?.categoryTtlMs
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Whether an SPL token account exists at `ata`. Cached under {@link SPL_ATA_CACHE_CATEGORY};
|
|
206
|
+
* clear via post-success `splAta` transaction cache invalidations after successful creates.
|
|
207
|
+
*/
|
|
208
|
+
async splAtaExists(ata) {
|
|
209
|
+
const { data } = await this.dataCache.getData(
|
|
210
|
+
async () => (await fetchMaybeToken(this.rpc, ata)).exists,
|
|
211
|
+
SPL_ATA_CACHE_CATEGORY,
|
|
212
|
+
ata
|
|
213
|
+
);
|
|
214
|
+
return data ?? false;
|
|
215
|
+
}
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
// ../../shared/common/src/utils/solana.ts
|
|
219
|
+
import {
|
|
220
|
+
createKeyPairSignerFromBytes
|
|
221
|
+
} from "@solana/kit";
|
|
222
|
+
import { Keypair } from "@solana/web3.js";
|
|
223
|
+
|
|
224
|
+
// ../../shared/common/src/utils/general.ts
|
|
225
|
+
function deduplicateAccounts(addresses) {
|
|
226
|
+
return Array.from(new Set(addresses).values());
|
|
227
|
+
}
|
|
228
|
+
function dedupeOrdered(items, key) {
|
|
229
|
+
const ordered = [];
|
|
230
|
+
const seen = /* @__PURE__ */ new Set();
|
|
231
|
+
for (const item of items) {
|
|
232
|
+
const k = key(item);
|
|
233
|
+
if (seen.has(k)) continue;
|
|
234
|
+
seen.add(k);
|
|
235
|
+
ordered.push(item);
|
|
236
|
+
}
|
|
237
|
+
return ordered;
|
|
238
|
+
}
|
|
239
|
+
function dedupeOrderedAddresses(addresses) {
|
|
240
|
+
return dedupeOrdered(addresses, (a) => a);
|
|
241
|
+
}
|
|
242
|
+
function filterSpecificAccounts(addresses, excluded) {
|
|
243
|
+
const excludedSet = new Set(excluded);
|
|
244
|
+
return addresses.filter((address9) => !excludedSet.has(address9));
|
|
245
|
+
}
|
|
246
|
+
function zip(list1, list2) {
|
|
247
|
+
const minLength = Math.min(list1.length, list2.length);
|
|
248
|
+
const result = [];
|
|
249
|
+
for (let i = 0; i < minLength; i++) {
|
|
250
|
+
result.push([list1[i], list2[i]]);
|
|
251
|
+
}
|
|
252
|
+
return result;
|
|
253
|
+
}
|
|
254
|
+
function maxByNumber(items, score) {
|
|
255
|
+
if (items.length === 0) {
|
|
256
|
+
throw new Error("maxByNumber: empty items");
|
|
257
|
+
}
|
|
258
|
+
let best = items[0];
|
|
259
|
+
let bestScore = score(best);
|
|
260
|
+
for (let i = 1; i < items.length; i++) {
|
|
261
|
+
const item = items[i];
|
|
262
|
+
const s = score(item);
|
|
263
|
+
if (s > bestScore) {
|
|
264
|
+
best = item;
|
|
265
|
+
bestScore = s;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
return best;
|
|
269
|
+
}
|
|
270
|
+
function createRecord(keys, values) {
|
|
271
|
+
return Object.fromEntries(zip(keys, values).map(([k, v]) => [k.toString(), v]));
|
|
272
|
+
}
|
|
273
|
+
function findKeyIgnoreCase(record, key) {
|
|
274
|
+
const lower = key.toLowerCase();
|
|
275
|
+
return Object.keys(record).find((k) => k.toLowerCase() === lower);
|
|
276
|
+
}
|
|
277
|
+
function sleep(ms) {
|
|
278
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// ../../shared/common/src/utils/solana.ts
|
|
282
|
+
function createSignerFromAddress(address9) {
|
|
283
|
+
return { address: address9 };
|
|
284
|
+
}
|
|
285
|
+
async function getSlot(rpc, commitment = "confirmed") {
|
|
286
|
+
return rpc.getSlot({ commitment }).send();
|
|
287
|
+
}
|
|
288
|
+
function isTransactionSigner(x) {
|
|
289
|
+
return typeof x === "object" && x !== null && "address" in x && typeof x.address === "string";
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// ../../shared/common/src/utils/accounts/pda.ts
|
|
293
|
+
import { ASSOCIATED_TOKEN_PROGRAM_ADDRESS, TOKEN_PROGRAM_ADDRESS } from "@solana-program/token";
|
|
294
|
+
import { PublicKey as PublicKey2 } from "@solana/web3.js";
|
|
295
|
+
|
|
296
|
+
// ../../shared/common/src/utils/compat.ts
|
|
297
|
+
import { PublicKey } from "@solana/web3.js";
|
|
298
|
+
import { AccountRole, address as address2 } from "@solana/kit";
|
|
299
|
+
function toWeb3Pk(addr) {
|
|
300
|
+
return new PublicKey(addr);
|
|
301
|
+
}
|
|
302
|
+
function fromWeb3Pk(addr) {
|
|
303
|
+
return address2(addr.toString());
|
|
304
|
+
}
|
|
305
|
+
function toWeb3AccountMeta(account) {
|
|
306
|
+
return {
|
|
307
|
+
pubkey: new PublicKey(account.address),
|
|
308
|
+
isSigner: account.role === AccountRole.READONLY_SIGNER || account.role === AccountRole.WRITABLE_SIGNER,
|
|
309
|
+
isWritable: account.role === AccountRole.WRITABLE || account.role === AccountRole.WRITABLE_SIGNER
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
function toKitInstruction(ix) {
|
|
313
|
+
return {
|
|
314
|
+
programAddress: ix.programId.toBase58(),
|
|
315
|
+
data: new Uint8Array(ix.data),
|
|
316
|
+
accounts: ix.keys.map((key) => ({
|
|
317
|
+
address: key.pubkey.toBase58(),
|
|
318
|
+
role: key.isWritable ? key.isSigner ? AccountRole.WRITABLE_SIGNER : AccountRole.WRITABLE : key.isSigner ? AccountRole.READONLY_SIGNER : AccountRole.READONLY
|
|
319
|
+
}))
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// ../../shared/common/src/utils/accounts/pda.ts
|
|
324
|
+
function deriveAssociatedTokenAddress(mint, owner, tokenProgram) {
|
|
325
|
+
const [ata] = PublicKey2.findProgramAddressSync(
|
|
326
|
+
[toWeb3Pk(owner).toBuffer(), toWeb3Pk(tokenProgram).toBuffer(), toWeb3Pk(mint).toBuffer()],
|
|
327
|
+
new PublicKey2(ASSOCIATED_TOKEN_PROGRAM_ADDRESS)
|
|
328
|
+
);
|
|
329
|
+
return fromWeb3Pk(ata);
|
|
330
|
+
}
|
|
331
|
+
async function getAtaAddress(mint, owner, tokenProgram = TOKEN_PROGRAM_ADDRESS) {
|
|
332
|
+
return deriveAssociatedTokenAddress(mint, owner, tokenProgram);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
// ../../shared/common/src/utils/accounts/rpc.ts
|
|
336
|
+
async function allAccountsExist(rpc, addresses) {
|
|
337
|
+
if (!addresses.length) {
|
|
338
|
+
return {
|
|
339
|
+
existingAddresses: [],
|
|
340
|
+
missingAddresses: [],
|
|
341
|
+
existsByAddress: /* @__PURE__ */ new Map()
|
|
342
|
+
};
|
|
343
|
+
}
|
|
344
|
+
const uniqueAddresses = [...new Set(addresses)];
|
|
345
|
+
const response = await rpc.getMultipleAccounts(uniqueAddresses, { encoding: "base64" }).send();
|
|
346
|
+
const existsByAddress = /* @__PURE__ */ new Map();
|
|
347
|
+
for (let i = 0; i < uniqueAddresses.length; i += 1) {
|
|
348
|
+
existsByAddress.set(uniqueAddresses[i], response.value[i] !== null);
|
|
349
|
+
}
|
|
350
|
+
return {
|
|
351
|
+
existingAddresses: uniqueAddresses.filter((address9) => existsByAddress.get(address9)),
|
|
352
|
+
missingAddresses: uniqueAddresses.filter((address9) => !existsByAddress.get(address9)),
|
|
353
|
+
existsByAddress
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
async function accountExists(rpc, address9) {
|
|
357
|
+
const accountInfo = await rpc.getAccountInfo(address9, { encoding: "base64" }).send();
|
|
358
|
+
return accountInfo.value !== null;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// ../../shared/common/src/services/mints/registry.ts
|
|
362
|
+
import { TOKEN_PROGRAM_ADDRESS as TOKEN_PROGRAM_ADDRESS2 } from "@solana-program/token";
|
|
363
|
+
import { TOKEN_2022_PROGRAM_ADDRESS } from "@solana-program/token-2022";
|
|
364
|
+
|
|
365
|
+
// ../../shared/common/src/services/mints/defaults.ts
|
|
366
|
+
import { address as address3 } from "@solana/kit";
|
|
367
|
+
var DEFAULT_MINTS = [
|
|
368
|
+
// Risk assets
|
|
369
|
+
{
|
|
370
|
+
address: address3("So11111111111111111111111111111111111111112"),
|
|
371
|
+
symbol: "SOL",
|
|
372
|
+
name: "Solana",
|
|
373
|
+
decimals: 9,
|
|
374
|
+
assetType: "Standard"
|
|
375
|
+
},
|
|
376
|
+
{
|
|
377
|
+
address: address3("3NZ9JMVBmGAqocybic2c7LQCJScmgsAZ6vQqTDzcqmJh"),
|
|
378
|
+
symbol: "wBTC",
|
|
379
|
+
name: "Wrapped Bitcoin",
|
|
380
|
+
decimals: 8,
|
|
381
|
+
assetType: "Standard"
|
|
382
|
+
},
|
|
383
|
+
{
|
|
384
|
+
address: address3("cbbtcf3aa214zXHbiAZQwf4122FBYbraNdFqgw4iMij"),
|
|
385
|
+
symbol: "cbBTC",
|
|
386
|
+
name: "Coinbase Wrapped Bitcoin",
|
|
387
|
+
decimals: 8,
|
|
388
|
+
assetType: "Standard"
|
|
389
|
+
},
|
|
390
|
+
{
|
|
391
|
+
address: address3("7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs"),
|
|
392
|
+
symbol: "wETH",
|
|
393
|
+
name: "Wrapped Ethereum",
|
|
394
|
+
decimals: 8,
|
|
395
|
+
assetType: "Standard"
|
|
396
|
+
},
|
|
397
|
+
{
|
|
398
|
+
address: address3("27G8MtK7VtTcCHkpASjSDdkWWYfoqT6ggEuKidVJidD4"),
|
|
399
|
+
symbol: "JLP",
|
|
400
|
+
name: "Jupiter Perps LP",
|
|
401
|
+
decimals: 6,
|
|
402
|
+
assetType: "Standard"
|
|
403
|
+
},
|
|
404
|
+
{
|
|
405
|
+
address: address3("XsoCS1TfEyfFhfvj8EtZ528L3CaKBDBRqRapnBbDF2W"),
|
|
406
|
+
symbol: "SPYx",
|
|
407
|
+
name: "SP500 xStock",
|
|
408
|
+
decimals: 8,
|
|
409
|
+
assetType: "Standard",
|
|
410
|
+
isToken2022: true
|
|
411
|
+
},
|
|
412
|
+
{
|
|
413
|
+
address: address3("Xs8S1uUs1zvS2p7iwtsG3b6fkhpvmwz4GYU3gWAmWHZ"),
|
|
414
|
+
symbol: "QQQx",
|
|
415
|
+
name: "Nasdaq xStock",
|
|
416
|
+
decimals: 8,
|
|
417
|
+
assetType: "Standard",
|
|
418
|
+
isToken2022: true
|
|
419
|
+
},
|
|
420
|
+
// Stablecoins
|
|
421
|
+
{
|
|
422
|
+
address: address3("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"),
|
|
423
|
+
symbol: "USDC",
|
|
424
|
+
name: "USD Coin",
|
|
425
|
+
decimals: 6,
|
|
426
|
+
assetType: "Stablecoin"
|
|
427
|
+
},
|
|
428
|
+
{
|
|
429
|
+
address: address3("Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB"),
|
|
430
|
+
symbol: "USDT",
|
|
431
|
+
name: "Tether USD",
|
|
432
|
+
decimals: 6,
|
|
433
|
+
assetType: "Stablecoin"
|
|
434
|
+
},
|
|
435
|
+
{
|
|
436
|
+
address: address3("USDSwr9ApdHk5bvJKMjzff41FfuX8bSxdKcR81vTwcA"),
|
|
437
|
+
symbol: "USDS",
|
|
438
|
+
decimals: 6,
|
|
439
|
+
assetType: "Stablecoin"
|
|
440
|
+
},
|
|
441
|
+
{
|
|
442
|
+
address: address3("2u1tszSeqZ3qBWF3uNGPFc8TzMk2tdiwknnRMWGWjGWH"),
|
|
443
|
+
symbol: "USDG",
|
|
444
|
+
name: "Global Dollar",
|
|
445
|
+
decimals: 6,
|
|
446
|
+
assetType: "Stablecoin",
|
|
447
|
+
isToken2022: true
|
|
448
|
+
},
|
|
449
|
+
{
|
|
450
|
+
address: address3("2b1kV6DkPAnxd5ixfnxCpjxmKwqjjaYmCZfHsFu24GXo"),
|
|
451
|
+
symbol: "PYUSD",
|
|
452
|
+
name: "PayPal USD",
|
|
453
|
+
decimals: 6,
|
|
454
|
+
assetType: "Stablecoin",
|
|
455
|
+
isToken2022: true
|
|
456
|
+
},
|
|
457
|
+
{
|
|
458
|
+
address: address3("CASHx9KJUStyftLFWGvEVf59SGeG9sh5FfcnZMVPCASH"),
|
|
459
|
+
symbol: "CASH",
|
|
460
|
+
decimals: 6,
|
|
461
|
+
assetType: "Stablecoin",
|
|
462
|
+
isToken2022: true
|
|
463
|
+
},
|
|
464
|
+
{
|
|
465
|
+
address: address3("USD1ttGY1N17NEEHLmELoaybftRBUSErhqYiQzvEmuB"),
|
|
466
|
+
symbol: "USD1",
|
|
467
|
+
decimals: 6,
|
|
468
|
+
assetType: "Stablecoin"
|
|
469
|
+
},
|
|
470
|
+
// LSTs
|
|
471
|
+
{
|
|
472
|
+
address: address3("J1toso1uCk3RLmjorhTtrVwY9HJ7X8V9yYac6Y7kGCPn"),
|
|
473
|
+
symbol: "JitoSOL",
|
|
474
|
+
name: "Jito SOL",
|
|
475
|
+
decimals: 9,
|
|
476
|
+
assetType: "LST"
|
|
477
|
+
},
|
|
478
|
+
{
|
|
479
|
+
address: address3("jupSoLaHXQiZZTSfEWMTRRgpnyFm8f6sZdosWBjx93v"),
|
|
480
|
+
symbol: "JupSOL",
|
|
481
|
+
name: "Jupiter Staked SOL",
|
|
482
|
+
decimals: 9,
|
|
483
|
+
assetType: "LST"
|
|
484
|
+
},
|
|
485
|
+
{
|
|
486
|
+
address: address3("sctmB7GPi5L2Q5G9tUSzXvhZ4YiDMEGcRov9KfArQpx"),
|
|
487
|
+
symbol: "dfdvSOL",
|
|
488
|
+
name: "DeFi Development Corp SOL",
|
|
489
|
+
decimals: 9,
|
|
490
|
+
assetType: "LST"
|
|
491
|
+
},
|
|
492
|
+
// Yield bearing assets
|
|
493
|
+
{
|
|
494
|
+
address: address3("star9agSpjiFe3M49B3RniVU4CMBBEK3Qnaqn3RGiFM"),
|
|
495
|
+
symbol: "USD*",
|
|
496
|
+
name: "USD Star",
|
|
497
|
+
decimals: 6,
|
|
498
|
+
assetType: "YBA"
|
|
499
|
+
},
|
|
500
|
+
{
|
|
501
|
+
address: address3("3AJYCjrhKitmBd8tRUurPA5dGHCAQh6A8L9DkuSC37Rm"),
|
|
502
|
+
symbol: "USD*-J",
|
|
503
|
+
name: "USD Star Junior",
|
|
504
|
+
decimals: 6,
|
|
505
|
+
assetType: "YBA"
|
|
506
|
+
},
|
|
507
|
+
{
|
|
508
|
+
address: address3("59obFNBzyTBGowrkif5uK7ojS58vsuWz3ZCvg6tfZAGw"),
|
|
509
|
+
symbol: "PST",
|
|
510
|
+
name: "PayFi Strategy Token",
|
|
511
|
+
decimals: 6,
|
|
512
|
+
assetType: "YBA"
|
|
513
|
+
}
|
|
514
|
+
];
|
|
515
|
+
|
|
516
|
+
// ../../shared/common/src/utils/numbers.ts
|
|
517
|
+
import { BN } from "@anchor-lang/core";
|
|
518
|
+
var U64_MAX = BigInt("18446744073709551615");
|
|
519
|
+
var U64_MAX_BN = new BN(U64_MAX.toString());
|
|
520
|
+
function toUiAmount(amount, decimals) {
|
|
521
|
+
const bigintValue = typeof amount === "bigint" ? amount : BigInt(amount.toString());
|
|
522
|
+
if (bigintValue >= U64_MAX) {
|
|
523
|
+
return Infinity;
|
|
524
|
+
}
|
|
525
|
+
if (bigintValue <= BigInt(Number.MAX_SAFE_INTEGER)) {
|
|
526
|
+
return Number(bigintValue) / Math.pow(10, decimals);
|
|
527
|
+
}
|
|
528
|
+
const divisor = BigInt(Math.pow(10, decimals));
|
|
529
|
+
const wholePart = bigintValue / divisor;
|
|
530
|
+
const remainder = bigintValue % divisor;
|
|
531
|
+
return Number(wholePart) + Number(remainder) / Math.pow(10, decimals);
|
|
532
|
+
}
|
|
533
|
+
function fromUiAmount(amount, decimals) {
|
|
534
|
+
return new BN(Math.round(amount * Math.pow(10, decimals)));
|
|
535
|
+
}
|
|
536
|
+
function wholeTokenAmount(decimals) {
|
|
537
|
+
return Math.pow(10, decimals);
|
|
538
|
+
}
|
|
539
|
+
function calculateTvlUsd(amount, price, decimals) {
|
|
540
|
+
const assetScale = BigInt(wholeTokenAmount(decimals));
|
|
541
|
+
const scaleFactor = assetScale * assetScale / TVL_USD_SCALE;
|
|
542
|
+
return amount * price / scaleFactor;
|
|
543
|
+
}
|
|
544
|
+
function tvlUsdToBaseUnits(tvlUsd, price, decimals) {
|
|
545
|
+
const assetScale = BigInt(wholeTokenAmount(decimals));
|
|
546
|
+
const scaleFactor = assetScale * assetScale / TVL_USD_SCALE;
|
|
547
|
+
return tvlUsd * scaleFactor / price;
|
|
548
|
+
}
|
|
549
|
+
function bnFromBigInt(n) {
|
|
550
|
+
return new BN(n.toString());
|
|
551
|
+
}
|
|
552
|
+
function applyFeeCeil(principal, feeRate) {
|
|
553
|
+
if (feeRate <= 0) return 0n;
|
|
554
|
+
const scale = 1000000000n;
|
|
555
|
+
const rateScaled = BigInt(Math.ceil(feeRate * Number(scale)));
|
|
556
|
+
const numerator = principal * rateScaled;
|
|
557
|
+
return (numerator + (scale - 1n)) / scale;
|
|
558
|
+
}
|
|
559
|
+
function getBatches(items, batchSize) {
|
|
560
|
+
const batches = [];
|
|
561
|
+
for (let i = 0; i < items.length; i += batchSize) {
|
|
562
|
+
batches.push(items.slice(i, i + batchSize));
|
|
563
|
+
}
|
|
564
|
+
return batches;
|
|
565
|
+
}
|
|
566
|
+
function currentUnixSeconds() {
|
|
567
|
+
return Math.floor(Date.now() / 1e3);
|
|
568
|
+
}
|
|
569
|
+
function sum(numbers) {
|
|
570
|
+
return numbers.reduce((prev, curr) => prev + curr, 0);
|
|
571
|
+
}
|
|
572
|
+
function toBigInt(value) {
|
|
573
|
+
return BigInt(value.toString());
|
|
574
|
+
}
|
|
575
|
+
function applyBps(value, bps) {
|
|
576
|
+
return value * BigInt(bps) / BPS_DENOMINATOR;
|
|
577
|
+
}
|
|
578
|
+
function toSafeNumber(value, field) {
|
|
579
|
+
const asBigInt = typeof value === "bigint" ? value : BigInt(value.toString());
|
|
580
|
+
if (asBigInt > BigInt(Number.MAX_SAFE_INTEGER)) {
|
|
581
|
+
throw new Error(`${field} exceeds Number.MAX_SAFE_INTEGER and cannot be quoted safely`);
|
|
582
|
+
}
|
|
583
|
+
return Number(asBigInt);
|
|
584
|
+
}
|
|
585
|
+
function numberToLEBytes(value, byteLength = 8) {
|
|
586
|
+
const bigintValue = typeof value === "bigint" ? value : BigInt(value.toString());
|
|
587
|
+
const buf = new ArrayBuffer(byteLength);
|
|
588
|
+
const view = new DataView(buf);
|
|
589
|
+
if (byteLength === 8) {
|
|
590
|
+
view.setBigUint64(0, bigintValue, true);
|
|
591
|
+
} else {
|
|
592
|
+
let remaining = bigintValue;
|
|
593
|
+
for (let i = 0; i < byteLength; i++) {
|
|
594
|
+
view.setUint8(i, Number(remaining & 0xffn));
|
|
595
|
+
remaining >>= 8n;
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
return new Uint8Array(buf);
|
|
599
|
+
}
|
|
600
|
+
function numToU64Bytes(value) {
|
|
601
|
+
return numberToLEBytes(value, 8);
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
// ../../shared/common/src/services/mints/registry.ts
|
|
605
|
+
var MintRegistry = class {
|
|
606
|
+
constructor(options = {}) {
|
|
607
|
+
this.byAddress = /* @__PURE__ */ new Map();
|
|
608
|
+
this.bySymbol = /* @__PURE__ */ new Map();
|
|
609
|
+
const { includeDefaults = true, custom = [] } = options;
|
|
610
|
+
if (includeDefaults) {
|
|
611
|
+
for (const config of DEFAULT_MINTS) {
|
|
612
|
+
this.register(config);
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
for (const config of custom) {
|
|
616
|
+
this.register(config);
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
/**
|
|
620
|
+
* Register a new mint configuration.
|
|
621
|
+
* Overwrites existing entries with the same address or symbol.
|
|
622
|
+
*/
|
|
623
|
+
register(config) {
|
|
624
|
+
const mintInfo = {
|
|
625
|
+
...config,
|
|
626
|
+
tokenProgram: config.isToken2022 ? TOKEN_2022_PROGRAM_ADDRESS : TOKEN_PROGRAM_ADDRESS2,
|
|
627
|
+
toUiAmount: (amount) => toUiAmount(amount, config.decimals),
|
|
628
|
+
fromUiAmount: (amount) => fromUiAmount(amount, config.decimals)
|
|
629
|
+
};
|
|
630
|
+
this.byAddress.set(config.address, mintInfo);
|
|
631
|
+
this.bySymbol.set(config.symbol.toUpperCase(), mintInfo);
|
|
632
|
+
}
|
|
633
|
+
/**
|
|
634
|
+
* Get mint information by address or symbol.
|
|
635
|
+
*
|
|
636
|
+
* @param mint - Mint address or token symbol (case-insensitive)
|
|
637
|
+
* @returns MintInfo if found, undefined otherwise
|
|
638
|
+
*
|
|
639
|
+
* @example
|
|
640
|
+
* ```typescript
|
|
641
|
+
* mints.get("USDC")?.decimals // 6
|
|
642
|
+
* mints.get(usdcAddress)?.symbol // "USDC"
|
|
643
|
+
* ```
|
|
644
|
+
*/
|
|
645
|
+
get(mint) {
|
|
646
|
+
const upperKey = mint.toUpperCase();
|
|
647
|
+
const bySymbol = this.bySymbol.get(upperKey);
|
|
648
|
+
if (bySymbol) {
|
|
649
|
+
return bySymbol;
|
|
650
|
+
}
|
|
651
|
+
return this.byAddress.get(mint);
|
|
652
|
+
}
|
|
653
|
+
all() {
|
|
654
|
+
return Array.from(this.byAddress.values());
|
|
655
|
+
}
|
|
656
|
+
standardAssets() {
|
|
657
|
+
return this.filterAssetsByType("Standard");
|
|
658
|
+
}
|
|
659
|
+
stablecoins() {
|
|
660
|
+
return this.filterAssetsByType("Stablecoin");
|
|
661
|
+
}
|
|
662
|
+
lsts() {
|
|
663
|
+
return this.filterAssetsByType("LST");
|
|
664
|
+
}
|
|
665
|
+
yieldBearingAssets() {
|
|
666
|
+
return this.filterAssetsByType("YBA");
|
|
667
|
+
}
|
|
668
|
+
filterAssetsByType(assetType) {
|
|
669
|
+
return Array.from(this.byAddress.values()).filter((x) => x.assetType === assetType);
|
|
670
|
+
}
|
|
671
|
+
symbols() {
|
|
672
|
+
return Array.from(this.bySymbol.keys());
|
|
673
|
+
}
|
|
674
|
+
addresses() {
|
|
675
|
+
return Array.from(this.byAddress.keys());
|
|
676
|
+
}
|
|
677
|
+
};
|
|
678
|
+
var mints = new MintRegistry();
|
|
679
|
+
|
|
680
|
+
// ../../shared/common/src/services/mints/symbols.ts
|
|
681
|
+
function mintSymbol(mint, registry = mints) {
|
|
682
|
+
return registry.get(mint)?.symbol ?? String(mint).slice(0, 6);
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
// ../../shared/common/src/utils/instruction.ts
|
|
686
|
+
function setComputeUnitLimitIx(maxComputeUnits) {
|
|
687
|
+
return getSetComputeUnitLimitInstruction({
|
|
688
|
+
units: maxComputeUnits
|
|
689
|
+
});
|
|
690
|
+
}
|
|
691
|
+
function setComputeUnitPriceIx(microLamports) {
|
|
692
|
+
return getSetComputeUnitPriceInstruction({
|
|
693
|
+
microLamports
|
|
694
|
+
});
|
|
695
|
+
}
|
|
696
|
+
function requestHeapFrameIx(bytes) {
|
|
697
|
+
return getRequestHeapFrameInstruction({ bytes });
|
|
698
|
+
}
|
|
699
|
+
async function getCreateAtaInstructions(rpc, payer, accounts) {
|
|
700
|
+
const requiredAtas = accounts.filter((x) => x.isRequiredAta);
|
|
701
|
+
if (!requiredAtas.length) {
|
|
702
|
+
return { instructions: [], postSuccessCacheInvalidations: [] };
|
|
703
|
+
}
|
|
704
|
+
const { existsByAddress } = await allAccountsExist(
|
|
705
|
+
rpc,
|
|
706
|
+
requiredAtas.map((account) => account.address)
|
|
707
|
+
);
|
|
708
|
+
const payerSigner = createSignerFromAddress(payer);
|
|
709
|
+
const instructions = [];
|
|
710
|
+
const postSuccessCacheInvalidations = [];
|
|
711
|
+
for (const account of requiredAtas) {
|
|
712
|
+
if (!existsByAddress.get(account.address)) {
|
|
713
|
+
const seeds = account.isRequiredAta;
|
|
714
|
+
instructions.push(
|
|
715
|
+
getCreateAssociatedTokenIdempotentInstruction({
|
|
716
|
+
payer: payerSigner,
|
|
717
|
+
ata: account.address,
|
|
718
|
+
owner: seeds.owner,
|
|
719
|
+
mint: seeds.mint,
|
|
720
|
+
tokenProgram: seeds.tokenProgram
|
|
721
|
+
})
|
|
722
|
+
);
|
|
723
|
+
postSuccessCacheInvalidations.push({ client: SPL_ATA_CACHE_CATEGORY, ata: account.address });
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
return { instructions, postSuccessCacheInvalidations };
|
|
727
|
+
}
|
|
728
|
+
async function getCreateAtaIxIfNeeded(rpc, payer, mint, owner, tokenProgram = TOKEN_PROGRAM_ADDRESS3, options) {
|
|
729
|
+
const ata = await getAtaAddress(mint, owner, tokenProgram);
|
|
730
|
+
const exists = options?.accountClient !== void 0 ? await options.accountClient.splAtaExists(ata) : (await fetchMaybeToken2(rpc, ata)).exists;
|
|
731
|
+
if (exists) {
|
|
732
|
+
return { instruction: null, postSuccessCacheInvalidations: [] };
|
|
733
|
+
}
|
|
734
|
+
const payerSigner = isTransactionSigner(payer) ? payer : createSignerFromAddress(payer);
|
|
735
|
+
const instruction = getCreateAssociatedTokenIdempotentInstruction({
|
|
736
|
+
payer: payerSigner,
|
|
737
|
+
ata,
|
|
738
|
+
owner,
|
|
739
|
+
mint,
|
|
740
|
+
tokenProgram
|
|
741
|
+
});
|
|
742
|
+
return {
|
|
743
|
+
instruction,
|
|
744
|
+
postSuccessCacheInvalidations: [{ client: SPL_ATA_CACHE_CATEGORY, ata }]
|
|
745
|
+
};
|
|
746
|
+
}
|
|
747
|
+
async function getWrapSolInstructions(rpc, owner, payer, lamports, createAtaOptions) {
|
|
748
|
+
const solMint = mints.get("SOL");
|
|
749
|
+
const solMintAddress = solMint.address;
|
|
750
|
+
const ata = await getAtaAddress(solMintAddress, owner);
|
|
751
|
+
const { instruction: createAtaIx, postSuccessCacheInvalidations } = await getCreateAtaIxIfNeeded(
|
|
752
|
+
rpc,
|
|
753
|
+
payer,
|
|
754
|
+
solMintAddress,
|
|
755
|
+
owner,
|
|
756
|
+
TOKEN_PROGRAM_ADDRESS3,
|
|
757
|
+
createAtaOptions
|
|
758
|
+
);
|
|
759
|
+
const instructions = [];
|
|
760
|
+
if (createAtaIx) instructions.push(createAtaIx);
|
|
761
|
+
instructions.push(
|
|
762
|
+
getTransferSolInstruction({
|
|
763
|
+
source: payer,
|
|
764
|
+
destination: ata,
|
|
765
|
+
amount: BigInt(lamports.toString())
|
|
766
|
+
}),
|
|
767
|
+
getSyncNativeInstruction({ account: ata })
|
|
768
|
+
);
|
|
769
|
+
return { instructions, postSuccessCacheInvalidations };
|
|
770
|
+
}
|
|
771
|
+
async function getUnwrapSolInstruction(owner, destination) {
|
|
772
|
+
const solMint = mints.get("SOL");
|
|
773
|
+
if (!solMint) throw new Error("WSOL mint not found in registry");
|
|
774
|
+
const solMintAddress = solMint.address;
|
|
775
|
+
const ata = await getAtaAddress(solMintAddress, owner.address);
|
|
776
|
+
return getCloseAccountInstruction({
|
|
777
|
+
account: ata,
|
|
778
|
+
destination: destination ?? owner.address,
|
|
779
|
+
owner
|
|
780
|
+
});
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
// ../../shared/common/src/services/lutManager.ts
|
|
784
|
+
import { getProgramDerivedAddress as getProgramDerivedAddress2, getAddressEncoder as getAddressEncoder2, getU64Encoder } from "@solana/kit";
|
|
785
|
+
import {
|
|
786
|
+
getCreateLookupTableInstruction,
|
|
787
|
+
getExtendLookupTableInstruction,
|
|
788
|
+
fetchAddressLookupTable,
|
|
789
|
+
ADDRESS_LOOKUP_TABLE_PROGRAM_ADDRESS
|
|
790
|
+
} from "@solana-program/address-lookup-table";
|
|
791
|
+
|
|
792
|
+
// ../../shared/common/src/utils/accounts/roles.ts
|
|
793
|
+
import { AccountRole as AccountRole2, upgradeRoleToSigner, upgradeRoleToWritable } from "@solana/kit";
|
|
794
|
+
function isRoleWritable(role) {
|
|
795
|
+
return role === AccountRole2.WRITABLE || role === AccountRole2.WRITABLE_SIGNER;
|
|
796
|
+
}
|
|
797
|
+
function isRoleSigner(role) {
|
|
798
|
+
return role === AccountRole2.READONLY_SIGNER || role === AccountRole2.WRITABLE_SIGNER;
|
|
799
|
+
}
|
|
800
|
+
function getAccountRole(isWritable, isSigner) {
|
|
801
|
+
let role = AccountRole2.READONLY;
|
|
802
|
+
if (isWritable) role = upgradeRoleToWritable(role);
|
|
803
|
+
if (isSigner) role = upgradeRoleToSigner(role);
|
|
804
|
+
return role;
|
|
805
|
+
}
|
|
806
|
+
function downgradeRoleFromSigner(role) {
|
|
807
|
+
if (role === AccountRole2.READONLY_SIGNER) return AccountRole2.READONLY;
|
|
808
|
+
if (role === AccountRole2.WRITABLE_SIGNER) return AccountRole2.WRITABLE;
|
|
809
|
+
return role;
|
|
810
|
+
}
|
|
811
|
+
function stripSignerFromAccounts(accounts) {
|
|
812
|
+
return accounts.map((acc) => ({
|
|
813
|
+
...acc,
|
|
814
|
+
role: downgradeRoleFromSigner(acc.role)
|
|
815
|
+
}));
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
// ../../shared/common/src/utils/accounts/meta.ts
|
|
819
|
+
function toCustomAccountMeta(address9, isWritable, requiredAtaDetails, isSigner) {
|
|
820
|
+
const role = getAccountRole(isWritable ?? false, isSigner ?? false);
|
|
821
|
+
return { address: address9, role, isRequiredAta: requiredAtaDetails };
|
|
822
|
+
}
|
|
823
|
+
function toCustomAccountMetaFromWeb3AccountMeta(web3AccountMeta) {
|
|
824
|
+
return toCustomAccountMeta(
|
|
825
|
+
web3AccountMeta.pubkey.toBase58(),
|
|
826
|
+
web3AccountMeta.isWritable,
|
|
827
|
+
void 0,
|
|
828
|
+
web3AccountMeta.isSigner
|
|
829
|
+
);
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
// ../../shared/common/src/utils/accounts/splBalances.ts
|
|
833
|
+
var SPL_TOKEN_ACCOUNT_AMOUNT_OFFSET = 64;
|
|
834
|
+
var GET_MULTIPLE_ACCOUNTS_MAX_KEYS = 100;
|
|
835
|
+
async function fetchSplTokenAccountAmounts(rpc, tokenAccounts) {
|
|
836
|
+
if (tokenAccounts.length === 0) return /* @__PURE__ */ new Map();
|
|
837
|
+
const chunks = [];
|
|
838
|
+
for (let i = 0; i < tokenAccounts.length; i += GET_MULTIPLE_ACCOUNTS_MAX_KEYS) {
|
|
839
|
+
chunks.push(tokenAccounts.slice(i, i + GET_MULTIPLE_ACCOUNTS_MAX_KEYS));
|
|
840
|
+
}
|
|
841
|
+
const balances = /* @__PURE__ */ new Map();
|
|
842
|
+
await Promise.all(
|
|
843
|
+
chunks.map(async (chunk) => {
|
|
844
|
+
const response = await rpc.getMultipleAccounts(chunk, { encoding: "base64" }).send();
|
|
845
|
+
for (let i = 0; i < chunk.length; i++) {
|
|
846
|
+
const entry = response.value[i];
|
|
847
|
+
if (!entry) continue;
|
|
848
|
+
const buf = Buffer.from(entry.data[0], "base64");
|
|
849
|
+
balances.set(chunk[i], buf.readBigUInt64LE(SPL_TOKEN_ACCOUNT_AMOUNT_OFFSET));
|
|
850
|
+
}
|
|
851
|
+
})
|
|
852
|
+
);
|
|
853
|
+
return balances;
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
// ../../shared/common/src/utils/data.ts
|
|
857
|
+
function applyDataCacheTransactionInvalidations(dataCache, invalidations, options) {
|
|
858
|
+
for (const inv of invalidations) {
|
|
859
|
+
if (inv.client === "lycToken") {
|
|
860
|
+
dataCache.clearCacheEntry(options.tokenPdaCategory, inv.tokenPda);
|
|
861
|
+
} else if (inv.client === "lycYieldingBank") {
|
|
862
|
+
dataCache.clearCacheEntry(options.yieldingBankPdaCategory, inv.yieldingBankPda);
|
|
863
|
+
} else if (inv.client === "splAta") {
|
|
864
|
+
dataCache.clearCacheEntry(SPL_ATA_CACHE_CATEGORY, inv.ata);
|
|
865
|
+
} else if (inv.client === "perena") {
|
|
866
|
+
inv.dataCache.clearCacheEntry(inv.category, inv.id);
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
// ../../shared/common/src/utils/cpi/args.ts
|
|
872
|
+
var SKIP_SENTINEL = 65535;
|
|
873
|
+
function serializeArgs(data) {
|
|
874
|
+
if (data === void 0) {
|
|
875
|
+
const buf2 = Buffer.alloc(2);
|
|
876
|
+
buf2.writeUInt16LE(SKIP_SENTINEL);
|
|
877
|
+
return buf2;
|
|
878
|
+
}
|
|
879
|
+
const len = data.length;
|
|
880
|
+
const buf = Buffer.alloc(2 + len);
|
|
881
|
+
buf.writeUInt16LE(len);
|
|
882
|
+
if (len > 0) {
|
|
883
|
+
Buffer.from(data).copy(buf, 2);
|
|
884
|
+
}
|
|
885
|
+
return buf;
|
|
886
|
+
}
|
|
887
|
+
var CpiArgsBuilder = class {
|
|
888
|
+
constructor() {
|
|
889
|
+
this.parts = [];
|
|
890
|
+
}
|
|
891
|
+
/**
|
|
892
|
+
* Add client-provided args for the next CPI slot.
|
|
893
|
+
* Automatically wraps with a u16 LE length prefix.
|
|
894
|
+
*/
|
|
895
|
+
add(data) {
|
|
896
|
+
this.parts.push(serializeArgs(data));
|
|
897
|
+
return this;
|
|
898
|
+
}
|
|
899
|
+
/**
|
|
900
|
+
* Mark the next CPI slot as a no-args instruction (length = 0).
|
|
901
|
+
* The Rust side will invoke the CPI with empty instruction data.
|
|
902
|
+
*/
|
|
903
|
+
noArgs() {
|
|
904
|
+
this.parts.push(serializeArgs(Buffer.alloc(0)));
|
|
905
|
+
return this;
|
|
906
|
+
}
|
|
907
|
+
/**
|
|
908
|
+
* Mark the next CPI slot as program-provided (sentinel 0xFFFF).
|
|
909
|
+
* The Rust handler must compute args and call `invoke_cpi` directly.
|
|
910
|
+
*/
|
|
911
|
+
skip() {
|
|
912
|
+
this.parts.push(serializeArgs());
|
|
913
|
+
return this;
|
|
914
|
+
}
|
|
915
|
+
/** Build the final packed buffer. */
|
|
916
|
+
build() {
|
|
917
|
+
return Buffer.concat(this.parts);
|
|
918
|
+
}
|
|
919
|
+
};
|
|
920
|
+
|
|
921
|
+
// ../../shared/common/src/utils/cpi/refs.ts
|
|
922
|
+
import { upgradeRoleToSigner as upgradeRoleToSigner2, upgradeRoleToWritable as upgradeRoleToWritable2 } from "@solana/kit";
|
|
923
|
+
function buildIndicesForCpi(accounts, poolIndex) {
|
|
924
|
+
return accounts.map((acc) => {
|
|
925
|
+
const idx = poolIndex.get(acc.address);
|
|
926
|
+
if (idx === void 0) {
|
|
927
|
+
throw new Error(`Account ${acc.address} not found in pool`);
|
|
928
|
+
}
|
|
929
|
+
return idx;
|
|
930
|
+
});
|
|
931
|
+
}
|
|
932
|
+
function buildDeduplicatedPool(accountLists) {
|
|
933
|
+
const poolMap = /* @__PURE__ */ new Map();
|
|
934
|
+
for (const accounts of accountLists) {
|
|
935
|
+
for (const acc of accounts) {
|
|
936
|
+
const existing = poolMap.get(acc.address);
|
|
937
|
+
if (!existing) {
|
|
938
|
+
poolMap.set(acc.address, { ...acc });
|
|
939
|
+
} else {
|
|
940
|
+
if (isRoleWritable(acc.role) && !isRoleWritable(existing.role)) {
|
|
941
|
+
existing.role = upgradeRoleToWritable2(existing.role);
|
|
942
|
+
}
|
|
943
|
+
if (isRoleSigner(acc.role) && !isRoleSigner(existing.role)) {
|
|
944
|
+
existing.role = upgradeRoleToSigner2(existing.role);
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
return poolMap;
|
|
950
|
+
}
|
|
951
|
+
function buildPoolWithOrderedInitial(initialAccounts, accountLists) {
|
|
952
|
+
const pool = initialAccounts.map((acc) => ({ ...acc }));
|
|
953
|
+
const poolIndex = /* @__PURE__ */ new Map();
|
|
954
|
+
pool.forEach((acc, i) => {
|
|
955
|
+
if (!poolIndex.has(acc.address)) {
|
|
956
|
+
poolIndex.set(acc.address, i);
|
|
957
|
+
}
|
|
958
|
+
});
|
|
959
|
+
for (const accounts of accountLists) {
|
|
960
|
+
for (const acc of accounts) {
|
|
961
|
+
const existingIdx = poolIndex.get(acc.address);
|
|
962
|
+
if (existingIdx === void 0) {
|
|
963
|
+
const idx = pool.length;
|
|
964
|
+
poolIndex.set(acc.address, idx);
|
|
965
|
+
pool.push({ ...acc });
|
|
966
|
+
} else {
|
|
967
|
+
const existing = pool[existingIdx];
|
|
968
|
+
if (isRoleWritable(acc.role) && !isRoleWritable(existing.role)) {
|
|
969
|
+
existing.role = upgradeRoleToWritable2(existing.role);
|
|
970
|
+
}
|
|
971
|
+
if (isRoleSigner(acc.role) && !isRoleSigner(existing.role)) {
|
|
972
|
+
existing.role = upgradeRoleToSigner2(existing.role);
|
|
973
|
+
}
|
|
974
|
+
}
|
|
975
|
+
}
|
|
976
|
+
}
|
|
977
|
+
return { pool, poolIndex };
|
|
978
|
+
}
|
|
979
|
+
function buildPool(accountLists, options) {
|
|
980
|
+
if (options?.initialAccounts) {
|
|
981
|
+
return buildPoolWithOrderedInitial(options.initialAccounts, accountLists);
|
|
982
|
+
}
|
|
983
|
+
const poolMap = buildDeduplicatedPool(accountLists);
|
|
984
|
+
const pool = Array.from(poolMap.values());
|
|
985
|
+
const poolIndex = /* @__PURE__ */ new Map();
|
|
986
|
+
pool.forEach((acc, i) => poolIndex.set(acc.address, i));
|
|
987
|
+
return { pool, poolIndex };
|
|
988
|
+
}
|
|
989
|
+
function resolveTrackedIndices(poolIndex, trackAddresses) {
|
|
990
|
+
if (!trackAddresses) return [];
|
|
991
|
+
return trackAddresses.map((addr) => {
|
|
992
|
+
const idx = poolIndex.get(addr);
|
|
993
|
+
if (idx === void 0) {
|
|
994
|
+
throw new Error(`Tracked address ${addr} not found in pool`);
|
|
995
|
+
}
|
|
996
|
+
return idx;
|
|
997
|
+
});
|
|
998
|
+
}
|
|
999
|
+
function buildInstructionRefs(cpis, accountLists, poolIndex, trackedIndices) {
|
|
1000
|
+
const allIndices = [];
|
|
1001
|
+
const lengths = [];
|
|
1002
|
+
const cpiTypes = [];
|
|
1003
|
+
const cpiArgs = new CpiArgsBuilder();
|
|
1004
|
+
for (let i = 0; i < cpis.length; i++) {
|
|
1005
|
+
const indices = buildIndicesForCpi(accountLists[i], poolIndex);
|
|
1006
|
+
allIndices.push(...indices);
|
|
1007
|
+
lengths.push(indices.length);
|
|
1008
|
+
cpiTypes.push(cpis[i].cpiType);
|
|
1009
|
+
if (cpis[i].data !== void 0) {
|
|
1010
|
+
cpiArgs.add(cpis[i].data);
|
|
1011
|
+
} else {
|
|
1012
|
+
cpiArgs.skip();
|
|
1013
|
+
}
|
|
1014
|
+
}
|
|
1015
|
+
return {
|
|
1016
|
+
cpi: {
|
|
1017
|
+
accounts: {
|
|
1018
|
+
indices: Buffer.from(allIndices),
|
|
1019
|
+
lengths: Buffer.from(lengths)
|
|
1020
|
+
},
|
|
1021
|
+
types: Buffer.from(cpiTypes),
|
|
1022
|
+
args: cpiArgs.build()
|
|
1023
|
+
},
|
|
1024
|
+
tracked: Buffer.from(trackedIndices)
|
|
1025
|
+
};
|
|
1026
|
+
}
|
|
1027
|
+
function toCpiAccountLists(cpis) {
|
|
1028
|
+
return cpis.map((cpi) => [toCustomAccountMeta(cpi.programId), ...cpi.accounts]);
|
|
1029
|
+
}
|
|
1030
|
+
function collectLookupTables(cpis) {
|
|
1031
|
+
return cpis.flatMap((x) => x.lookupTables ?? []);
|
|
1032
|
+
}
|
|
1033
|
+
function createMultiCpiRefs(cpiGroups, options) {
|
|
1034
|
+
const allCpis = cpiGroups.flat();
|
|
1035
|
+
const allAccountLists = toCpiAccountLists(allCpis);
|
|
1036
|
+
const { pool, poolIndex } = buildPool(allAccountLists, options);
|
|
1037
|
+
const trackedIndices = resolveTrackedIndices(poolIndex, options?.trackAddresses);
|
|
1038
|
+
let flatIdx = 0;
|
|
1039
|
+
const refsGroups = cpiGroups.map((group) => {
|
|
1040
|
+
const groupAccountLists = allAccountLists.slice(flatIdx, flatIdx + group.length);
|
|
1041
|
+
flatIdx += group.length;
|
|
1042
|
+
return buildInstructionRefs(group, groupAccountLists, poolIndex, trackedIndices);
|
|
1043
|
+
});
|
|
1044
|
+
return {
|
|
1045
|
+
accounts: stripSignerFromAccounts(pool),
|
|
1046
|
+
refsGroups,
|
|
1047
|
+
lookupTables: collectLookupTables(allCpis)
|
|
1048
|
+
};
|
|
1049
|
+
}
|
|
1050
|
+
function createCpiRefs(cpis, options) {
|
|
1051
|
+
const accountLists = toCpiAccountLists(cpis);
|
|
1052
|
+
const { pool, poolIndex } = buildPool(accountLists, options);
|
|
1053
|
+
const trackedIndices = resolveTrackedIndices(poolIndex, options?.trackAddresses);
|
|
1054
|
+
return {
|
|
1055
|
+
accounts: stripSignerFromAccounts(pool),
|
|
1056
|
+
refs: buildInstructionRefs(cpis, accountLists, poolIndex, trackedIndices),
|
|
1057
|
+
lookupTables: collectLookupTables(cpis)
|
|
1058
|
+
};
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1061
|
+
// ../../shared/common/src/utils/rpc.ts
|
|
1062
|
+
import {
|
|
1063
|
+
createDefaultRpcTransport,
|
|
1064
|
+
createSolanaRpc,
|
|
1065
|
+
createSolanaRpcFromTransport
|
|
1066
|
+
} from "@solana/kit";
|
|
1067
|
+
|
|
1068
|
+
// ../../shared/common/src/utils/retry.ts
|
|
1069
|
+
var DEFAULT_MAX_ATTEMPTS = 4;
|
|
1070
|
+
var INITIAL_DELAY_MS = 200;
|
|
1071
|
+
var MAX_DELAY_MS = 2e3;
|
|
1072
|
+
function isTransientNetworkError(err) {
|
|
1073
|
+
if (err instanceof TypeError) return true;
|
|
1074
|
+
const msg = (err?.message ?? "").toLowerCase();
|
|
1075
|
+
return msg.includes("fetch failed") || msg.includes("econnreset") || msg.includes("econnrefused") || msg.includes("etimedout") || msg.includes("socket hang up") || msg.includes("network timeout") || msg.includes("all providers failed") || msg.includes("all rpc providers failed") || msg.includes("failed to get info about account") || msg.includes("429") || msg.includes("rate limit") || msg.includes("too many requests") || msg.includes("timeout") || // Local validators / forked RPCs can intermittently surface account-load
|
|
1076
|
+
// issues as a generic internal JSON-RPC error before the account is warmed.
|
|
1077
|
+
msg.includes("json-rpc error: internal json-rpc error") || msg.includes("json-rpc error: internal error");
|
|
1078
|
+
}
|
|
1079
|
+
function retryDelay(attempt) {
|
|
1080
|
+
return Math.min(INITIAL_DELAY_MS * 2 ** attempt, MAX_DELAY_MS);
|
|
1081
|
+
}
|
|
1082
|
+
async function withNetworkRetry(fn, maxAttempts = DEFAULT_MAX_ATTEMPTS) {
|
|
1083
|
+
let lastErr;
|
|
1084
|
+
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
1085
|
+
try {
|
|
1086
|
+
return await fn();
|
|
1087
|
+
} catch (err) {
|
|
1088
|
+
lastErr = err;
|
|
1089
|
+
if (!isTransientNetworkError(err) || attempt === maxAttempts - 1) break;
|
|
1090
|
+
await sleep(retryDelay(attempt));
|
|
1091
|
+
}
|
|
1092
|
+
}
|
|
1093
|
+
throw lastErr;
|
|
1094
|
+
}
|
|
1095
|
+
function fetchWithRetry(input, init) {
|
|
1096
|
+
return withNetworkRetry(() => fetch(input, init));
|
|
1097
|
+
}
|
|
1098
|
+
|
|
1099
|
+
// ../../shared/common/src/utils/rpc.ts
|
|
1100
|
+
function createRpcWithRetry(url) {
|
|
1101
|
+
const inner = createDefaultRpcTransport({ url });
|
|
1102
|
+
const retryingTransport = async (...args) => withNetworkRetry(() => inner(...args));
|
|
1103
|
+
return createSolanaRpcFromTransport(retryingTransport);
|
|
1104
|
+
}
|
|
1105
|
+
function createRpcWithFailover(urls) {
|
|
1106
|
+
const uniqueUrls = uniqueRpcUrls(urls);
|
|
1107
|
+
if (uniqueUrls.length === 0) {
|
|
1108
|
+
throw new Error("createRpcWithFailover requires at least one RPC URL");
|
|
1109
|
+
}
|
|
1110
|
+
if (uniqueUrls.length === 1) {
|
|
1111
|
+
return createRpcWithRetry(uniqueUrls[0]);
|
|
1112
|
+
}
|
|
1113
|
+
const providers = uniqueUrls.map((url) => ({
|
|
1114
|
+
url,
|
|
1115
|
+
transport: createDefaultRpcTransport({ url })
|
|
1116
|
+
}));
|
|
1117
|
+
const failoverTransport = async (...args) => {
|
|
1118
|
+
const failures = [];
|
|
1119
|
+
for (const provider of providers) {
|
|
1120
|
+
try {
|
|
1121
|
+
return await withNetworkRetry(() => provider.transport(...args));
|
|
1122
|
+
} catch (err) {
|
|
1123
|
+
if (!isTransientNetworkError(err)) {
|
|
1124
|
+
throw err;
|
|
1125
|
+
}
|
|
1126
|
+
failures.push(
|
|
1127
|
+
`${redactRpcUrlForLog(provider.url)}: ${err instanceof Error ? err.message : String(err)}`
|
|
1128
|
+
);
|
|
1129
|
+
}
|
|
1130
|
+
}
|
|
1131
|
+
throw new Error(`All RPC providers failed: ${failures.join(" | ")}`);
|
|
1132
|
+
};
|
|
1133
|
+
return createSolanaRpcFromTransport(failoverTransport);
|
|
1134
|
+
}
|
|
1135
|
+
function createRpc(environment) {
|
|
1136
|
+
const urls = getRpcUrls(environment);
|
|
1137
|
+
if (environment === "local") return createSolanaRpc(urls[0]);
|
|
1138
|
+
return createRpcWithFailover(urls);
|
|
1139
|
+
}
|
|
1140
|
+
function heliusRpcUrl(heliusApiKey) {
|
|
1141
|
+
return `https://mainnet.helius-rpc.com/?api-key=${heliusApiKey}`;
|
|
1142
|
+
}
|
|
1143
|
+
function ironforgeRpcUrl(ironforgeApiKey) {
|
|
1144
|
+
return `https://rpc.ironforge.network/mainnet?apiKey=${ironforgeApiKey}`;
|
|
1145
|
+
}
|
|
1146
|
+
var PUBLIC_MAINNET_RPC_URL = "https://api.mainnet-beta.solana.com";
|
|
1147
|
+
function getRpcUrl(environment) {
|
|
1148
|
+
return getRpcUrls(environment)[0];
|
|
1149
|
+
}
|
|
1150
|
+
function getRpcUrls(environment) {
|
|
1151
|
+
if (environment === "local") return ["http://127.0.0.1:8899"];
|
|
1152
|
+
const urls = uniqueRpcUrls([
|
|
1153
|
+
process.env.IRONFORGE_API_KEY ? ironforgeRpcUrl(process.env.IRONFORGE_API_KEY) : void 0,
|
|
1154
|
+
process.env.RPC_URL,
|
|
1155
|
+
process.env.HELIUS_API_KEY ? heliusRpcUrl(process.env.HELIUS_API_KEY) : void 0
|
|
1156
|
+
]);
|
|
1157
|
+
if (urls.length > 0) return urls;
|
|
1158
|
+
throw new Error(
|
|
1159
|
+
"Non-local environment requires an RPC endpoint. Set RPC_URL, IRONFORGE_API_KEY, or HELIUS_API_KEY."
|
|
1160
|
+
);
|
|
1161
|
+
}
|
|
1162
|
+
function getMainnetRpcUrl() {
|
|
1163
|
+
try {
|
|
1164
|
+
return getRpcUrl("prod");
|
|
1165
|
+
} catch {
|
|
1166
|
+
return PUBLIC_MAINNET_RPC_URL;
|
|
1167
|
+
}
|
|
1168
|
+
}
|
|
1169
|
+
function redactRpcUrlForLog(url) {
|
|
1170
|
+
return url.replace(/([?&]api-key=)[^&]*/gi, "$1\u2026").replace(/([?&]apiKey=)[^&]*/gi, "$1\u2026");
|
|
1171
|
+
}
|
|
1172
|
+
function uniqueRpcUrls(urls) {
|
|
1173
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1174
|
+
const unique = [];
|
|
1175
|
+
for (const url of urls) {
|
|
1176
|
+
if (!url) continue;
|
|
1177
|
+
const normalized = url.trim();
|
|
1178
|
+
if (!normalized || seen.has(normalized)) continue;
|
|
1179
|
+
seen.add(normalized);
|
|
1180
|
+
unique.push(normalized);
|
|
1181
|
+
}
|
|
1182
|
+
return unique;
|
|
1183
|
+
}
|
|
1184
|
+
|
|
1185
|
+
// ../../shared/common/src/utils/jsonRpcFetch.ts
|
|
1186
|
+
var JsonRpcTransientError = class extends Error {
|
|
1187
|
+
constructor(message, suggestedDelayMs) {
|
|
1188
|
+
super(message);
|
|
1189
|
+
this.suggestedDelayMs = suggestedDelayMs;
|
|
1190
|
+
this.name = "JsonRpcTransientError";
|
|
1191
|
+
}
|
|
1192
|
+
};
|
|
1193
|
+
var RETRYABLE_HTTP = /* @__PURE__ */ new Set([408, 429, 502, 503, 504]);
|
|
1194
|
+
function parseRetryAfterMs(header) {
|
|
1195
|
+
if (!header) return void 0;
|
|
1196
|
+
const sec = Number(header.trim());
|
|
1197
|
+
if (Number.isFinite(sec) && sec >= 0) return Math.floor(sec * 1e3);
|
|
1198
|
+
return void 0;
|
|
1199
|
+
}
|
|
1200
|
+
function isRetryableJsonRpcError(err) {
|
|
1201
|
+
if (!err) return false;
|
|
1202
|
+
if (err.code === -32429) return true;
|
|
1203
|
+
return /rate limit/i.test(err.message);
|
|
1204
|
+
}
|
|
1205
|
+
async function jsonRpcFetchOnce(rpcUrl, method, params) {
|
|
1206
|
+
let res;
|
|
1207
|
+
try {
|
|
1208
|
+
res = await fetch(rpcUrl, {
|
|
1209
|
+
method: "POST",
|
|
1210
|
+
headers: { "Content-Type": "application/json" },
|
|
1211
|
+
body: JSON.stringify({ jsonrpc: "2.0", id: 1, method, params })
|
|
1212
|
+
});
|
|
1213
|
+
} catch (e) {
|
|
1214
|
+
const cause = e instanceof Error ? e.message : String(e);
|
|
1215
|
+
const local = rpcUrl.includes("127.0.0.1") || rpcUrl.includes("localhost") ? " No process is listening on that URL \u2014 start a local validator (e.g. surfpool/solana-test-validator) or set ENVIRONMENT + RPC_URL / HELIUS_API_KEY for a remote endpoint." : "";
|
|
1216
|
+
throw new JsonRpcTransientError(
|
|
1217
|
+
`RPC ${method} fetch failed (${redactRpcUrlForLog(rpcUrl)}): ${cause}.${local}`
|
|
1218
|
+
);
|
|
1219
|
+
}
|
|
1220
|
+
const retryAfterMs = parseRetryAfterMs(res.headers.get("Retry-After"));
|
|
1221
|
+
if (RETRYABLE_HTTP.has(res.status)) {
|
|
1222
|
+
const text = await res.text();
|
|
1223
|
+
throw new JsonRpcTransientError(`RPC ${method} HTTP ${res.status}: ${text}`, retryAfterMs);
|
|
1224
|
+
}
|
|
1225
|
+
if (!res.ok) {
|
|
1226
|
+
throw new Error(`RPC ${method} HTTP ${res.status}: ${await res.text()}`);
|
|
1227
|
+
}
|
|
1228
|
+
let body;
|
|
1229
|
+
try {
|
|
1230
|
+
body = await res.json();
|
|
1231
|
+
} catch {
|
|
1232
|
+
throw new JsonRpcTransientError(`RPC ${method}: invalid JSON response body`);
|
|
1233
|
+
}
|
|
1234
|
+
if (body.error) {
|
|
1235
|
+
const dataStr = body.error.data !== void 0 ? ` data=${JSON.stringify(body.error.data, (_, v) => typeof v === "bigint" ? v.toString() : v)}` : "";
|
|
1236
|
+
if (isRetryableJsonRpcError(body.error)) {
|
|
1237
|
+
throw new JsonRpcTransientError(
|
|
1238
|
+
`RPC ${method} error ${body.error.code}: ${body.error.message}${dataStr}`,
|
|
1239
|
+
retryAfterMs
|
|
1240
|
+
);
|
|
1241
|
+
}
|
|
1242
|
+
throw new Error(`RPC ${method} error ${body.error.code}: ${body.error.message}${dataStr}`);
|
|
1243
|
+
}
|
|
1244
|
+
return body.result;
|
|
1245
|
+
}
|
|
1246
|
+
|
|
1247
|
+
// ../../shared/common/src/utils/anchor.ts
|
|
1248
|
+
import * as anchor from "@anchor-lang/core";
|
|
1249
|
+
import { AnchorProvider } from "@anchor-lang/core";
|
|
1250
|
+
import { Connection, Keypair as Keypair2 } from "@solana/web3.js";
|
|
1251
|
+
var DEFAULT_COMMITMENT = "confirmed";
|
|
1252
|
+
function createDefaultAnchorProvider(env, walletOrKeypair, confirmOptions) {
|
|
1253
|
+
const commitment = confirmOptions?.commitment ?? DEFAULT_COMMITMENT;
|
|
1254
|
+
const wallet = walletOrKeypair instanceof Keypair2 ? new anchor.Wallet(walletOrKeypair) : walletOrKeypair;
|
|
1255
|
+
const opts = { commitment, ...confirmOptions };
|
|
1256
|
+
return new AnchorProvider(new Connection(getRpcUrl(env), commitment), wallet, opts);
|
|
1257
|
+
}
|
|
1258
|
+
function createReadOnlyAnchorProvider(env) {
|
|
1259
|
+
return createDefaultAnchorProvider(env, Keypair2.generate());
|
|
1260
|
+
}
|
|
1261
|
+
|
|
1262
|
+
// ../../shared/common/src/utils/transactionSplitter.ts
|
|
1263
|
+
import { compileTransaction, getBase64EncodedWireTransaction } from "@solana/kit";
|
|
1264
|
+
|
|
1265
|
+
// ../../shared/common/src/utils/jito.ts
|
|
1266
|
+
import { getTransferSolInstruction as getTransferSolInstruction2 } from "@solana-program/system";
|
|
1267
|
+
var MAX_BUNDLE_TRANSACTIONS = 5;
|
|
1268
|
+
var DEFAULT_JITO_TIP_LAMPORTS = 2e6;
|
|
1269
|
+
var JitoBundleError = class extends Error {
|
|
1270
|
+
constructor(message, bundleId) {
|
|
1271
|
+
super(message);
|
|
1272
|
+
this.bundleId = bundleId;
|
|
1273
|
+
this.name = "JitoBundleError";
|
|
1274
|
+
}
|
|
1275
|
+
};
|
|
1276
|
+
var JITO_TIP_ACCOUNTS = [
|
|
1277
|
+
"96gYZGLnJYVFmbjzopPSU6QiEV5fGqZNyN9nmNhvrZU5",
|
|
1278
|
+
"HFqU5x63VTqvQss8hp11i4wVV8bD44PvwucfZ2bU7gRe"
|
|
1279
|
+
];
|
|
1280
|
+
var BUNDLE_INJECTED_IX_RESERVED_BYTES = 64;
|
|
1281
|
+
function getRandomTipAccount() {
|
|
1282
|
+
return JITO_TIP_ACCOUNTS[Math.floor(Math.random() * JITO_TIP_ACCOUNTS.length)];
|
|
1283
|
+
}
|
|
1284
|
+
function buildTipInstruction(payer, tipAccount, lamports) {
|
|
1285
|
+
return getTransferSolInstruction2({
|
|
1286
|
+
source: payer,
|
|
1287
|
+
destination: tipAccount,
|
|
1288
|
+
amount: BigInt(lamports)
|
|
1289
|
+
});
|
|
1290
|
+
}
|
|
1291
|
+
async function sendBundle(rpcUrl, base64Txs) {
|
|
1292
|
+
if (base64Txs.length > MAX_BUNDLE_TRANSACTIONS) {
|
|
1293
|
+
throw new JitoBundleError(
|
|
1294
|
+
`Bundle has ${base64Txs.length} transactions, max is ${MAX_BUNDLE_TRANSACTIONS}`
|
|
1295
|
+
);
|
|
1296
|
+
}
|
|
1297
|
+
try {
|
|
1298
|
+
return await jsonRpcFetchOnce(rpcUrl, "sendBundle", [
|
|
1299
|
+
base64Txs,
|
|
1300
|
+
{ encoding: "base64" }
|
|
1301
|
+
]);
|
|
1302
|
+
} catch (e) {
|
|
1303
|
+
throw new JitoBundleError(`sendBundle failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
1304
|
+
}
|
|
1305
|
+
}
|
|
1306
|
+
async function simulateBundle(rpcUrl, base64Txs, options = {}) {
|
|
1307
|
+
const { skipSigVerify = true, replaceRecentBlockhash = true } = options;
|
|
1308
|
+
if (base64Txs.length > MAX_BUNDLE_TRANSACTIONS) {
|
|
1309
|
+
throw new JitoBundleError(
|
|
1310
|
+
`Bundle has ${base64Txs.length} transactions, max is ${MAX_BUNDLE_TRANSACTIONS}`
|
|
1311
|
+
);
|
|
1312
|
+
}
|
|
1313
|
+
try {
|
|
1314
|
+
const accountsConfigs = base64Txs.map(() => null);
|
|
1315
|
+
const raw = await jsonRpcFetchOnce(rpcUrl, "simulateBundle", [
|
|
1316
|
+
{ encodedTransactions: base64Txs },
|
|
1317
|
+
{
|
|
1318
|
+
preExecutionAccountsConfigs: accountsConfigs,
|
|
1319
|
+
postExecutionAccountsConfigs: accountsConfigs,
|
|
1320
|
+
skipSigVerify,
|
|
1321
|
+
replaceRecentBlockhash,
|
|
1322
|
+
transactionEncoding: "base64"
|
|
1323
|
+
}
|
|
1324
|
+
]);
|
|
1325
|
+
return "value" in raw && raw.value ? raw.value : raw;
|
|
1326
|
+
} catch (e) {
|
|
1327
|
+
throw new JitoBundleError(
|
|
1328
|
+
`simulateBundle failed: ${e instanceof Error ? e.message : String(e)}`
|
|
1329
|
+
);
|
|
1330
|
+
}
|
|
1331
|
+
}
|
|
1332
|
+
async function confirmBundle(rpcUrl, bundleId, timeoutMs = 6e4) {
|
|
1333
|
+
const pollIntervalMs = 1e3;
|
|
1334
|
+
const startTime = Date.now();
|
|
1335
|
+
while (Date.now() - startTime < timeoutMs) {
|
|
1336
|
+
await sleep(pollIntervalMs);
|
|
1337
|
+
let result;
|
|
1338
|
+
try {
|
|
1339
|
+
result = await jsonRpcFetchOnce(
|
|
1340
|
+
rpcUrl,
|
|
1341
|
+
"getBundleStatuses",
|
|
1342
|
+
[[bundleId]]
|
|
1343
|
+
);
|
|
1344
|
+
} catch (e) {
|
|
1345
|
+
console.warn(`[Jito] getBundleStatuses error: ${e instanceof Error ? e.message : String(e)}`);
|
|
1346
|
+
continue;
|
|
1347
|
+
}
|
|
1348
|
+
const entry = result.value?.[0];
|
|
1349
|
+
if (!entry) continue;
|
|
1350
|
+
if (entry.err != null && "Err" in entry.err) {
|
|
1351
|
+
throw new JitoBundleError(
|
|
1352
|
+
`Bundle ${bundleId} failed: ${JSON.stringify(entry.err)}`,
|
|
1353
|
+
bundleId
|
|
1354
|
+
);
|
|
1355
|
+
}
|
|
1356
|
+
if (entry.confirmation_status === "confirmed" || entry.confirmation_status === "finalized") {
|
|
1357
|
+
return { slot: entry.slot };
|
|
1358
|
+
}
|
|
1359
|
+
}
|
|
1360
|
+
throw new JitoBundleError(
|
|
1361
|
+
`Bundle ${bundleId} confirmation timeout after ${timeoutMs}ms`,
|
|
1362
|
+
bundleId
|
|
1363
|
+
);
|
|
1364
|
+
}
|
|
1365
|
+
|
|
1366
|
+
// ../../shared/common/src/utils/transactionSplitter.ts
|
|
1367
|
+
var SOLANA_TX_SIZE_LIMIT = 1232;
|
|
1368
|
+
function measureTxBytes(msg) {
|
|
1369
|
+
const compiled = compileTransaction(msg);
|
|
1370
|
+
const b64 = getBase64EncodedWireTransaction(compiled);
|
|
1371
|
+
return Math.ceil(b64.length * 3 / 4);
|
|
1372
|
+
}
|
|
1373
|
+
function buildInstructionSegments(instructions, segmentLengths) {
|
|
1374
|
+
if (segmentLengths === void 0 || segmentLengths.length === 0) {
|
|
1375
|
+
return instructions.map((ix) => [ix]);
|
|
1376
|
+
}
|
|
1377
|
+
const sum2 = segmentLengths.reduce((a, b) => a + b, 0);
|
|
1378
|
+
if (sum2 !== instructions.length) {
|
|
1379
|
+
throw new Error(
|
|
1380
|
+
`segmentLengths sum (${sum2}) must equal instructions.length (${instructions.length}).`
|
|
1381
|
+
);
|
|
1382
|
+
}
|
|
1383
|
+
if (segmentLengths.some((n) => !Number.isInteger(n) || n <= 0)) {
|
|
1384
|
+
throw new Error("segmentLengths entries must be positive integers.");
|
|
1385
|
+
}
|
|
1386
|
+
const segments = [];
|
|
1387
|
+
let offset = 0;
|
|
1388
|
+
for (const len of segmentLengths) {
|
|
1389
|
+
segments.push(instructions.slice(offset, offset + len));
|
|
1390
|
+
offset += len;
|
|
1391
|
+
}
|
|
1392
|
+
return segments;
|
|
1393
|
+
}
|
|
1394
|
+
async function splitIntoTransactionBins(rpc, payer, instructions, options = {}) {
|
|
1395
|
+
const {
|
|
1396
|
+
lookupTables,
|
|
1397
|
+
additionalSigners,
|
|
1398
|
+
blockhash,
|
|
1399
|
+
reservedBytes = 0,
|
|
1400
|
+
segmentLengths,
|
|
1401
|
+
freshBinSegments
|
|
1402
|
+
} = options;
|
|
1403
|
+
const effectiveLimit = SOLANA_TX_SIZE_LIMIT - reservedBytes;
|
|
1404
|
+
const freshBinSet = freshBinSegments ? new Set(freshBinSegments) : void 0;
|
|
1405
|
+
if (effectiveLimit <= 0) {
|
|
1406
|
+
throw new Error(
|
|
1407
|
+
`reservedBytes (${reservedBytes}) is >= the tx size limit (${SOLANA_TX_SIZE_LIMIT}).`
|
|
1408
|
+
);
|
|
1409
|
+
}
|
|
1410
|
+
const segments = buildInstructionSegments(instructions, segmentLengths);
|
|
1411
|
+
const bins = [];
|
|
1412
|
+
let currentBin = [];
|
|
1413
|
+
const measureCandidate = async (candidate) => {
|
|
1414
|
+
const msg = await buildTransactionMessage(
|
|
1415
|
+
rpc,
|
|
1416
|
+
payer,
|
|
1417
|
+
candidate,
|
|
1418
|
+
lookupTables,
|
|
1419
|
+
additionalSigners,
|
|
1420
|
+
blockhash
|
|
1421
|
+
);
|
|
1422
|
+
return measureTxBytes(msg);
|
|
1423
|
+
};
|
|
1424
|
+
for (let segIdx = 0; segIdx < segments.length; segIdx += 1) {
|
|
1425
|
+
const segment = segments[segIdx];
|
|
1426
|
+
if (freshBinSet?.has(segIdx) && currentBin.length > 0) {
|
|
1427
|
+
bins.push(currentBin);
|
|
1428
|
+
currentBin = [];
|
|
1429
|
+
}
|
|
1430
|
+
const candidate = [...currentBin, ...segment];
|
|
1431
|
+
const size = await measureCandidate(candidate);
|
|
1432
|
+
if (size <= effectiveLimit) {
|
|
1433
|
+
currentBin = candidate;
|
|
1434
|
+
continue;
|
|
1435
|
+
}
|
|
1436
|
+
if (currentBin.length === 0) {
|
|
1437
|
+
throw new Error(
|
|
1438
|
+
`An indivisible instruction group (${segment.length} instruction(s)) measures ${size} bytes, exceeding the ${effectiveLimit}-byte effective tx size limit (${SOLANA_TX_SIZE_LIMIT} - ${reservedBytes} reserved) even with address lookup tables. Cannot split.`
|
|
1439
|
+
);
|
|
1440
|
+
}
|
|
1441
|
+
bins.push(currentBin);
|
|
1442
|
+
currentBin = [...segment];
|
|
1443
|
+
const segmentSize = await measureCandidate(currentBin);
|
|
1444
|
+
if (segmentSize > effectiveLimit) {
|
|
1445
|
+
throw new Error(
|
|
1446
|
+
`An indivisible instruction group (${segment.length} instruction(s)) measures ${segmentSize} bytes, exceeding the ${effectiveLimit}-byte effective tx size limit (${SOLANA_TX_SIZE_LIMIT} - ${reservedBytes} reserved) even with address lookup tables. Cannot split.`
|
|
1447
|
+
);
|
|
1448
|
+
}
|
|
1449
|
+
}
|
|
1450
|
+
if (currentBin.length > 0) {
|
|
1451
|
+
bins.push(currentBin);
|
|
1452
|
+
}
|
|
1453
|
+
if (bins.length > MAX_BUNDLE_TRANSACTIONS) {
|
|
1454
|
+
throw new Error(
|
|
1455
|
+
`Instruction list requires ${bins.length} transactions, but Jito bundles allow at most ${MAX_BUNDLE_TRANSACTIONS}.`
|
|
1456
|
+
);
|
|
1457
|
+
}
|
|
1458
|
+
return { bins };
|
|
1459
|
+
}
|
|
1460
|
+
|
|
1461
|
+
// ../../shared/common/src/utils/txAccountCoverage.ts
|
|
1462
|
+
import { compileTransaction as compileTransaction2, getCompiledTransactionMessageDecoder } from "@solana/kit";
|
|
1463
|
+
|
|
1464
|
+
// ../../shared/common/src/utils/token.ts
|
|
1465
|
+
import { address as address4 } from "@solana/kit";
|
|
1466
|
+
import { BN as BN2 } from "@anchor-lang/core";
|
|
1467
|
+
import {
|
|
1468
|
+
getInitializeMint2Instruction,
|
|
1469
|
+
getMintSize,
|
|
1470
|
+
TOKEN_PROGRAM_ADDRESS as TOKEN_PROGRAM_ADDRESS4
|
|
1471
|
+
} from "@solana-program/token";
|
|
1472
|
+
import { TOKEN_2022_PROGRAM_ADDRESS as TOKEN_2022_PROGRAM_ADDRESS2 } from "@solana-program/token-2022";
|
|
1473
|
+
import { getCreateAccountInstruction } from "@solana-program/system";
|
|
1474
|
+
|
|
1475
|
+
// ../../shared/common/src/types/enums.ts
|
|
1476
|
+
function enumToOracleType(t) {
|
|
1477
|
+
switch (t) {
|
|
1478
|
+
case 0 /* Pyth */:
|
|
1479
|
+
return { pyth: {} };
|
|
1480
|
+
case 1 /* Switchboard */:
|
|
1481
|
+
return { switchboard: {} };
|
|
1482
|
+
case 2 /* PerenaBank */:
|
|
1483
|
+
return { perenaBank: {} };
|
|
1484
|
+
case 3 /* PerenaTranche */:
|
|
1485
|
+
return { perenaTranche: {} };
|
|
1486
|
+
case 4 /* PythSplStake */:
|
|
1487
|
+
return { pythSplStake: {} };
|
|
1488
|
+
case 5 /* TPConsensusOracle */:
|
|
1489
|
+
return { tpConsensusOracle: {} };
|
|
1490
|
+
}
|
|
1491
|
+
}
|
|
1492
|
+
function ExternalLiquidityTypeToEnum(v) {
|
|
1493
|
+
if ("none" in v) return 0 /* None */;
|
|
1494
|
+
if ("perenaWithdrawalQueue" in v) return 1 /* PerenaWithdrawalQueue */;
|
|
1495
|
+
throw new Error("Unknown ExternalLiquidityType variant");
|
|
1496
|
+
}
|
|
1497
|
+
function enumToExternalLiquidityType(t) {
|
|
1498
|
+
switch (t) {
|
|
1499
|
+
case 0 /* None */:
|
|
1500
|
+
return { none: {} };
|
|
1501
|
+
case 1 /* PerenaWithdrawalQueue */:
|
|
1502
|
+
return { perenaWithdrawalQueue: {} };
|
|
1503
|
+
}
|
|
1504
|
+
}
|
|
1505
|
+
function tokenProgramToEnum(v) {
|
|
1506
|
+
if ("spl" in v) return 0 /* Spl */;
|
|
1507
|
+
if ("token2022" in v) return 1 /* Token2022 */;
|
|
1508
|
+
throw new Error("Unknown TokenProgram variant");
|
|
1509
|
+
}
|
|
1510
|
+
function enumToTokenProgram(t) {
|
|
1511
|
+
switch (t) {
|
|
1512
|
+
case 0 /* Spl */:
|
|
1513
|
+
return { spl: {} };
|
|
1514
|
+
case 1 /* Token2022 */:
|
|
1515
|
+
return { token2022: {} };
|
|
1516
|
+
}
|
|
1517
|
+
}
|
|
1518
|
+
function lendingPlatformToEnum(v) {
|
|
1519
|
+
if ("none" in v) return 0 /* None */;
|
|
1520
|
+
if ("marginfi" in v) return 1 /* Marginfi */;
|
|
1521
|
+
if ("kamino" in v) return 2 /* Kamino */;
|
|
1522
|
+
throw new Error("Unknown LendingPlatform variant");
|
|
1523
|
+
}
|
|
1524
|
+
function enumToLendingPlatform(t) {
|
|
1525
|
+
switch (t) {
|
|
1526
|
+
case 0 /* None */:
|
|
1527
|
+
return { none: {} };
|
|
1528
|
+
case 1 /* Marginfi */:
|
|
1529
|
+
return { marginfi: {} };
|
|
1530
|
+
case 2 /* Kamino */:
|
|
1531
|
+
return { kamino: {} };
|
|
1532
|
+
}
|
|
1533
|
+
}
|
|
1534
|
+
|
|
1535
|
+
// ../../shared/common/src/utils/token.ts
|
|
1536
|
+
function resolveTokenProgram(tp) {
|
|
1537
|
+
return tokenProgramToEnum(tp) === 0 /* Spl */ ? TOKEN_PROGRAM_ADDRESS4 : TOKEN_2022_PROGRAM_ADDRESS2;
|
|
1538
|
+
}
|
|
1539
|
+
async function getCreateMintInstructions(rpc, payer, mintSigner, authority, decimals, tokenProgram = TOKEN_PROGRAM_ADDRESS4) {
|
|
1540
|
+
const space = getMintSize();
|
|
1541
|
+
const rent = await rpc.getMinimumBalanceForRentExemption(BigInt(space)).send();
|
|
1542
|
+
return [
|
|
1543
|
+
getCreateAccountInstruction({
|
|
1544
|
+
payer,
|
|
1545
|
+
newAccount: mintSigner,
|
|
1546
|
+
lamports: rent,
|
|
1547
|
+
space,
|
|
1548
|
+
programAddress: tokenProgram
|
|
1549
|
+
}),
|
|
1550
|
+
getInitializeMint2Instruction({
|
|
1551
|
+
mint: mintSigner.address,
|
|
1552
|
+
decimals,
|
|
1553
|
+
mintAuthority: authority
|
|
1554
|
+
})
|
|
1555
|
+
];
|
|
1556
|
+
}
|
|
1557
|
+
async function createMint(rpc, payer, mintSigner, authority, decimals, tokenProgram = TOKEN_PROGRAM_ADDRESS4) {
|
|
1558
|
+
const instructions = await getCreateMintInstructions(
|
|
1559
|
+
rpc,
|
|
1560
|
+
payer,
|
|
1561
|
+
mintSigner,
|
|
1562
|
+
authority,
|
|
1563
|
+
decimals,
|
|
1564
|
+
tokenProgram
|
|
1565
|
+
);
|
|
1566
|
+
await signSendAndConfirmTransaction(rpc, payer, instructions, {
|
|
1567
|
+
additionalSigners: [mintSigner]
|
|
1568
|
+
});
|
|
1569
|
+
}
|
|
1570
|
+
|
|
1571
|
+
// ../../shared/common/src/utils/metadata.ts
|
|
1572
|
+
import {
|
|
1573
|
+
AccountRole as AccountRole3,
|
|
1574
|
+
getAddressEncoder,
|
|
1575
|
+
getProgramDerivedAddress
|
|
1576
|
+
} from "@solana/kit";
|
|
1577
|
+
import { SYSTEM_PROGRAM_ADDRESS } from "@solana-program/system";
|
|
1578
|
+
import { SYSVAR_RENT_ADDRESS } from "@solana/sysvars";
|
|
1579
|
+
import {
|
|
1580
|
+
createUpdateMetadataAccountV2Instruction,
|
|
1581
|
+
createCreateMetadataAccountV3Instruction,
|
|
1582
|
+
Metadata
|
|
1583
|
+
} from "@metaplex-foundation/mpl-token-metadata";
|
|
1584
|
+
|
|
1585
|
+
// ../../shared/common/src/constants/generated/cpi.ts
|
|
1586
|
+
var CpiTypes = {
|
|
1587
|
+
JUPITER_SWAP: 0,
|
|
1588
|
+
PERENA_MINT: 1,
|
|
1589
|
+
PERENA_BURN: 2,
|
|
1590
|
+
PERENA_STAKE: 3,
|
|
1591
|
+
PERENA_INSTANT_UNSTAKE: 4,
|
|
1592
|
+
PERENA_REQUEST_UNSTAKE: 5,
|
|
1593
|
+
PERENA_FULFILL_UNSTAKE: 6,
|
|
1594
|
+
K_INIT_USER_METADATA: 7,
|
|
1595
|
+
K_INIT_OBLIGATION: 8,
|
|
1596
|
+
K_INIT_USER_FARM: 9,
|
|
1597
|
+
K_REFRESH_RESERVE: 10,
|
|
1598
|
+
K_REFRESH_OBLIGATION: 11,
|
|
1599
|
+
K_REFRESH_USER_FARM: 12,
|
|
1600
|
+
K_HARVEST_REWARD: 13,
|
|
1601
|
+
K_REQUEST_ELEVATION_GROUP: 14,
|
|
1602
|
+
K_DEPOSIT: 15,
|
|
1603
|
+
K_WITHDRAW: 16,
|
|
1604
|
+
K_BORROW: 17,
|
|
1605
|
+
K_REPAY: 18,
|
|
1606
|
+
MPL_UPDATE_METADATA: 19,
|
|
1607
|
+
MPL_CREATE_METADATA: 20
|
|
1608
|
+
};
|
|
1609
|
+
|
|
1610
|
+
// ../../shared/common/src/utils/metadata.ts
|
|
1611
|
+
var addressEncoder = getAddressEncoder();
|
|
1612
|
+
|
|
1613
|
+
// ../../shared/common/src/utils/priorityFee.ts
|
|
1614
|
+
import bs58 from "bs58";
|
|
1615
|
+
var MAX_COMPUTE_UNIT_PRICE_MICRO_LAMPORTS = 1e8;
|
|
1616
|
+
function normalizeEstimate(result) {
|
|
1617
|
+
const estimate = result.priorityFeeEstimate;
|
|
1618
|
+
if (typeof estimate === "bigint") {
|
|
1619
|
+
if (estimate < 0n) {
|
|
1620
|
+
throw new Error("Helius getPriorityFeeEstimate returned an invalid estimate");
|
|
1621
|
+
}
|
|
1622
|
+
return Number(
|
|
1623
|
+
estimate > BigInt(MAX_COMPUTE_UNIT_PRICE_MICRO_LAMPORTS) ? BigInt(MAX_COMPUTE_UNIT_PRICE_MICRO_LAMPORTS) : estimate
|
|
1624
|
+
);
|
|
1625
|
+
}
|
|
1626
|
+
if (estimate === void 0 || !Number.isFinite(estimate) || estimate < 0) {
|
|
1627
|
+
throw new Error("Helius getPriorityFeeEstimate returned an invalid estimate");
|
|
1628
|
+
}
|
|
1629
|
+
return Math.min(Math.round(estimate), MAX_COMPUTE_UNIT_PRICE_MICRO_LAMPORTS);
|
|
1630
|
+
}
|
|
1631
|
+
async function getPriorityFeeEstimate(rpc, transaction, accountKeys, priorityFeeSetting) {
|
|
1632
|
+
const transactionBase58 = bs58.encode(Buffer.from(transaction, "base64"));
|
|
1633
|
+
const priorityFeeRpc = rpc;
|
|
1634
|
+
try {
|
|
1635
|
+
const result = await priorityFeeRpc.getPriorityFeeEstimate({
|
|
1636
|
+
transaction: transactionBase58,
|
|
1637
|
+
options: { priorityLevel: priorityFeeSetting }
|
|
1638
|
+
}).send();
|
|
1639
|
+
return normalizeEstimate(result);
|
|
1640
|
+
} catch {
|
|
1641
|
+
const result = await priorityFeeRpc.getPriorityFeeEstimate({
|
|
1642
|
+
accountKeys,
|
|
1643
|
+
options: { priorityLevel: priorityFeeSetting }
|
|
1644
|
+
}).send();
|
|
1645
|
+
return normalizeEstimate(result);
|
|
1646
|
+
}
|
|
1647
|
+
}
|
|
1648
|
+
|
|
1649
|
+
// ../../shared/common/src/constants/accountMetas.ts
|
|
1650
|
+
import { SYSVAR_INSTRUCTIONS_ADDRESS, SYSVAR_RENT_ADDRESS as SYSVAR_RENT_ADDRESS2 } from "@solana/sysvars";
|
|
1651
|
+
import { SYSTEM_PROGRAM_ADDRESS as SYSTEM_PROGRAM_ADDRESS2 } from "@solana-program/system";
|
|
1652
|
+
var RENT_SYSVAR_META = toCustomAccountMeta(SYSVAR_RENT_ADDRESS2);
|
|
1653
|
+
var SYSTEM_PROGRAM_META = toCustomAccountMeta(SYSTEM_PROGRAM_ADDRESS2);
|
|
1654
|
+
var IX_SYSVAR_META = toCustomAccountMeta(SYSVAR_INSTRUCTIONS_ADDRESS);
|
|
1655
|
+
|
|
1656
|
+
// ../../shared/common/src/services/lutManager.ts
|
|
1657
|
+
var LUT_CACHE_CATEGORY = "lookupTable";
|
|
1658
|
+
var LutManager = class {
|
|
1659
|
+
constructor(cacheTtlConfig) {
|
|
1660
|
+
this.cache = new DataCache({
|
|
1661
|
+
defaultTtlMs: cacheTtlConfig?.defaultTtlMs ?? 6e4 * 15,
|
|
1662
|
+
categoryTtlMs: cacheTtlConfig?.categoryTtlMs
|
|
1663
|
+
});
|
|
1664
|
+
}
|
|
1665
|
+
/**
|
|
1666
|
+
* Fetch a single lookup table's data, with caching.
|
|
1667
|
+
*/
|
|
1668
|
+
async fetchLookupTable(rpc, address9) {
|
|
1669
|
+
const { data } = await this.cache.getDataOrThrow(
|
|
1670
|
+
async () => {
|
|
1671
|
+
const table = await fetchAddressLookupTable(rpc, address9);
|
|
1672
|
+
return {
|
|
1673
|
+
address: address9,
|
|
1674
|
+
addresses: table.data.addresses
|
|
1675
|
+
};
|
|
1676
|
+
},
|
|
1677
|
+
LUT_CACHE_CATEGORY,
|
|
1678
|
+
address9
|
|
1679
|
+
);
|
|
1680
|
+
return data;
|
|
1681
|
+
}
|
|
1682
|
+
/**
|
|
1683
|
+
* Fetch address lookup table data for the given addresses, with caching.
|
|
1684
|
+
*/
|
|
1685
|
+
async getLookupTableInputs(rpc, lookupTableAddresses) {
|
|
1686
|
+
return Promise.all(lookupTableAddresses.map((address9) => this.fetchLookupTable(rpc, address9)));
|
|
1687
|
+
}
|
|
1688
|
+
async addAddressesIfNeeded(signer, rpc, lookupTableAddress, existingAddresses, addressesToAdd) {
|
|
1689
|
+
const existingSet = new Set(existingAddresses);
|
|
1690
|
+
const addresses = addressesToAdd.filter((x) => !existingSet.has(x));
|
|
1691
|
+
if (addresses.length > 0) {
|
|
1692
|
+
const batches = getBatches(addresses, 20);
|
|
1693
|
+
for (const addressBatch of batches) {
|
|
1694
|
+
const extendIx = getExtendLookupTableInstruction({
|
|
1695
|
+
address: lookupTableAddress,
|
|
1696
|
+
authority: signer,
|
|
1697
|
+
payer: signer,
|
|
1698
|
+
addresses: addressBatch
|
|
1699
|
+
});
|
|
1700
|
+
await signSendAndConfirmTransaction(rpc, signer, [extendIx]);
|
|
1701
|
+
}
|
|
1702
|
+
}
|
|
1703
|
+
}
|
|
1704
|
+
async deriveLookupTableAddress(signerAddress, recentSlot) {
|
|
1705
|
+
const addressEncoder2 = getAddressEncoder2();
|
|
1706
|
+
const u64Encoder = getU64Encoder();
|
|
1707
|
+
return await getProgramDerivedAddress2({
|
|
1708
|
+
programAddress: ADDRESS_LOOKUP_TABLE_PROGRAM_ADDRESS,
|
|
1709
|
+
seeds: [addressEncoder2.encode(signerAddress), u64Encoder.encode(recentSlot)]
|
|
1710
|
+
});
|
|
1711
|
+
}
|
|
1712
|
+
async updateLookupTable(signer, rpc, accounts, existingLookupTableAddress) {
|
|
1713
|
+
if (existingLookupTableAddress === DEFAULT_PUBLIC_KEY) {
|
|
1714
|
+
existingLookupTableAddress = void 0;
|
|
1715
|
+
}
|
|
1716
|
+
let lookupTableAddress;
|
|
1717
|
+
let existingAccounts;
|
|
1718
|
+
if (existingLookupTableAddress) {
|
|
1719
|
+
lookupTableAddress = existingLookupTableAddress;
|
|
1720
|
+
const lutInput = await this.fetchLookupTable(rpc, lookupTableAddress);
|
|
1721
|
+
existingAccounts = lutInput.addresses;
|
|
1722
|
+
} else {
|
|
1723
|
+
const maxAttempts = 3;
|
|
1724
|
+
let lastError;
|
|
1725
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
1726
|
+
const slot = await getSlot(rpc, "finalized");
|
|
1727
|
+
const lutPda = await this.deriveLookupTableAddress(signer.address, slot);
|
|
1728
|
+
const createLutIx = getCreateLookupTableInstruction({
|
|
1729
|
+
address: lutPda,
|
|
1730
|
+
authority: signer,
|
|
1731
|
+
recentSlot: slot
|
|
1732
|
+
});
|
|
1733
|
+
try {
|
|
1734
|
+
await signSendAndConfirmTransaction(rpc, signer, [createLutIx], {
|
|
1735
|
+
hideFailureInfo: attempt < maxAttempts
|
|
1736
|
+
});
|
|
1737
|
+
lookupTableAddress = lutPda[0];
|
|
1738
|
+
console.log(`Created new lookup table: ${lookupTableAddress}`);
|
|
1739
|
+
this.cache.setCache(LUT_CACHE_CATEGORY, lookupTableAddress, {
|
|
1740
|
+
address: lookupTableAddress,
|
|
1741
|
+
addresses: []
|
|
1742
|
+
});
|
|
1743
|
+
lastError = void 0;
|
|
1744
|
+
break;
|
|
1745
|
+
} catch (e) {
|
|
1746
|
+
lastError = e;
|
|
1747
|
+
const errorStr = String(e);
|
|
1748
|
+
const logsStr = e instanceof TransactionError ? e.programLogs.join("\n") : "";
|
|
1749
|
+
const isStaleSlot = errorStr.includes("is not a recent slot") || logsStr.includes("is not a recent slot");
|
|
1750
|
+
if (isStaleSlot && attempt < maxAttempts) {
|
|
1751
|
+
console.warn(
|
|
1752
|
+
`LUT creation failed (stale slot ${slot}), retrying (${attempt}/${maxAttempts})...`
|
|
1753
|
+
);
|
|
1754
|
+
await new Promise((r) => setTimeout(r, 2e3));
|
|
1755
|
+
continue;
|
|
1756
|
+
}
|
|
1757
|
+
throw e;
|
|
1758
|
+
}
|
|
1759
|
+
}
|
|
1760
|
+
if (lastError) throw lastError;
|
|
1761
|
+
lookupTableAddress = lookupTableAddress;
|
|
1762
|
+
existingAccounts = [];
|
|
1763
|
+
}
|
|
1764
|
+
await this.addAddressesIfNeeded(
|
|
1765
|
+
signer,
|
|
1766
|
+
rpc,
|
|
1767
|
+
lookupTableAddress,
|
|
1768
|
+
existingAccounts,
|
|
1769
|
+
deduplicateAccounts(accounts).filter((x) => x !== DEFAULT_PUBLIC_KEY)
|
|
1770
|
+
);
|
|
1771
|
+
this.clearLookupTableCache(lookupTableAddress);
|
|
1772
|
+
return lookupTableAddress;
|
|
1773
|
+
}
|
|
1774
|
+
/**
|
|
1775
|
+
* Clear all cached lookup table data.
|
|
1776
|
+
*/
|
|
1777
|
+
clearCache() {
|
|
1778
|
+
this.cache.clearAllCache();
|
|
1779
|
+
}
|
|
1780
|
+
/**
|
|
1781
|
+
* Clear cached data for a specific lookup table.
|
|
1782
|
+
*/
|
|
1783
|
+
clearLookupTableCache(address9) {
|
|
1784
|
+
this.cache.clearCacheEntry(LUT_CACHE_CATEGORY, address9);
|
|
1785
|
+
}
|
|
1786
|
+
};
|
|
1787
|
+
var lutManager = new LutManager();
|
|
1788
|
+
|
|
1789
|
+
// ../../shared/common/src/utils/transaction.ts
|
|
1790
|
+
var MAX_COMPUTE_UNIT_LIMIT = 14e5;
|
|
1791
|
+
var DEFAULT_COMPUTE_UNIT_LIMIT_MULTIPLIER = 1.1;
|
|
1792
|
+
function computeUnitLimitFromSimulation(unitsConsumed, multiplier = DEFAULT_COMPUTE_UNIT_LIMIT_MULTIPLIER) {
|
|
1793
|
+
if (!(unitsConsumed > 0) || !(multiplier > 0)) {
|
|
1794
|
+
return MAX_COMPUTE_UNIT_LIMIT;
|
|
1795
|
+
}
|
|
1796
|
+
return Math.min(MAX_COMPUTE_UNIT_LIMIT, Math.ceil(unitsConsumed * multiplier));
|
|
1797
|
+
}
|
|
1798
|
+
function collectWritableAccounts(instructions) {
|
|
1799
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1800
|
+
const out = [];
|
|
1801
|
+
for (const ix of instructions) {
|
|
1802
|
+
for (const acc of ix.accounts ?? []) {
|
|
1803
|
+
const role = acc.role;
|
|
1804
|
+
if (role != null && (role & 1) === 1) {
|
|
1805
|
+
const addr = acc.address;
|
|
1806
|
+
if (!seen.has(addr)) {
|
|
1807
|
+
seen.add(addr);
|
|
1808
|
+
out.push(addr);
|
|
1809
|
+
}
|
|
1810
|
+
}
|
|
1811
|
+
}
|
|
1812
|
+
}
|
|
1813
|
+
return out;
|
|
1814
|
+
}
|
|
1815
|
+
async function signTransactionsWithSigners(transactions, signers) {
|
|
1816
|
+
let signedTransactions = [...transactions];
|
|
1817
|
+
const modifyingSigners = signers.filter(isTransactionModifyingSigner);
|
|
1818
|
+
const partialSigners = signers.filter(isTransactionPartialSigner);
|
|
1819
|
+
for (const signer of modifyingSigners) {
|
|
1820
|
+
signedTransactions = [...await signer.modifyAndSignTransactions(signedTransactions)];
|
|
1821
|
+
}
|
|
1822
|
+
for (const signer of partialSigners) {
|
|
1823
|
+
const signatures = await signer.signTransactions(signedTransactions);
|
|
1824
|
+
signedTransactions = signedTransactions.map((transaction, index) => ({
|
|
1825
|
+
...transaction,
|
|
1826
|
+
signatures: {
|
|
1827
|
+
...transaction.signatures,
|
|
1828
|
+
...signatures[index]
|
|
1829
|
+
}
|
|
1830
|
+
}));
|
|
1831
|
+
}
|
|
1832
|
+
for (const transaction of signedTransactions) {
|
|
1833
|
+
assertIsFullySignedTransaction(transaction);
|
|
1834
|
+
}
|
|
1835
|
+
return signedTransactions;
|
|
1836
|
+
}
|
|
1837
|
+
var TransactionError = class extends Error {
|
|
1838
|
+
constructor(message, programLogs = []) {
|
|
1839
|
+
super(programLogs.length ? `${message}
|
|
1840
|
+
|
|
1841
|
+
Program logs:
|
|
1842
|
+
${programLogs.join("\n")}` : message);
|
|
1843
|
+
this.name = "TransactionError";
|
|
1844
|
+
this.programLogs = programLogs;
|
|
1845
|
+
}
|
|
1846
|
+
};
|
|
1847
|
+
function logProgramLogsLineByLine(logs, label = "Program logs") {
|
|
1848
|
+
if (!logs.length) {
|
|
1849
|
+
console.error(`${label}: (no logs returned)`);
|
|
1850
|
+
return;
|
|
1851
|
+
}
|
|
1852
|
+
console.error(`${label} (${logs.length} lines):`);
|
|
1853
|
+
logs.forEach((line, index) => {
|
|
1854
|
+
console.error(`[${index}] ${line}`);
|
|
1855
|
+
});
|
|
1856
|
+
}
|
|
1857
|
+
async function resolvePriorityFeeMicroLamports(rpc, transactionMessage, writableAccounts, options) {
|
|
1858
|
+
if (options?.computeUnitPriceMicroLamports !== void 0) {
|
|
1859
|
+
return options.computeUnitPriceMicroLamports;
|
|
1860
|
+
}
|
|
1861
|
+
if (options?.priorityFeeSetting === void 0) {
|
|
1862
|
+
return void 0;
|
|
1863
|
+
}
|
|
1864
|
+
const estimateMessage = appendTransactionMessageInstructions(
|
|
1865
|
+
[setComputeUnitLimitIx(MAX_COMPUTE_UNIT_LIMIT)],
|
|
1866
|
+
transactionMessage
|
|
1867
|
+
);
|
|
1868
|
+
const estimateTransaction = getBase64EncodedWireTransaction2(compileTransaction3(estimateMessage));
|
|
1869
|
+
return getPriorityFeeEstimate(
|
|
1870
|
+
rpc,
|
|
1871
|
+
estimateTransaction,
|
|
1872
|
+
writableAccounts,
|
|
1873
|
+
options.priorityFeeSetting
|
|
1874
|
+
);
|
|
1875
|
+
}
|
|
1876
|
+
function getComputeBudgetInstructions(computeUnitLimit, priorityFeeMicroLamports) {
|
|
1877
|
+
return priorityFeeMicroLamports === void 0 ? [setComputeUnitLimitIx(computeUnitLimit)] : [setComputeUnitPriceIx(priorityFeeMicroLamports), setComputeUnitLimitIx(computeUnitLimit)];
|
|
1878
|
+
}
|
|
1879
|
+
async function buildTransactionMessage(rpc, feePayer, instructions, lookupTableAddresses, additionalSigners, blockhash) {
|
|
1880
|
+
const blockhashInfo = blockhash ?? (await rpc.getLatestBlockhash({ commitment: "confirmed" }).send()).value;
|
|
1881
|
+
let transactionMessage = pipe(
|
|
1882
|
+
createTransactionMessage({ version: 0 }),
|
|
1883
|
+
(tx) => setTransactionMessageFeePayerSigner(feePayer, tx),
|
|
1884
|
+
(tx) => setTransactionMessageLifetimeUsingBlockhash(blockhashInfo, tx),
|
|
1885
|
+
(tx) => appendTransactionMessageInstructions(instructions, tx)
|
|
1886
|
+
);
|
|
1887
|
+
const allSigners = [feePayer, ...additionalSigners ?? []];
|
|
1888
|
+
transactionMessage = addSignersToTransactionMessage(allSigners, transactionMessage);
|
|
1889
|
+
if (lookupTableAddresses?.length) {
|
|
1890
|
+
const lutInputs = await lutManager.getLookupTableInputs(
|
|
1891
|
+
rpc,
|
|
1892
|
+
deduplicateAccounts(lookupTableAddresses)
|
|
1893
|
+
);
|
|
1894
|
+
const lookupTables = {};
|
|
1895
|
+
for (const lut of lutInputs) {
|
|
1896
|
+
lookupTables[lut.address] = [...lut.addresses];
|
|
1897
|
+
}
|
|
1898
|
+
transactionMessage = compressTransactionMessageUsingAddressLookupTables(
|
|
1899
|
+
transactionMessage,
|
|
1900
|
+
lookupTables
|
|
1901
|
+
);
|
|
1902
|
+
}
|
|
1903
|
+
return transactionMessage;
|
|
1904
|
+
}
|
|
1905
|
+
async function simulateTransaction(rpc, transactionMessage) {
|
|
1906
|
+
const compiledTransaction = compileTransaction3(transactionMessage);
|
|
1907
|
+
const base64EncodedTransaction = getBase64EncodedWireTransaction2(compiledTransaction);
|
|
1908
|
+
const {
|
|
1909
|
+
value: { err, logs, unitsConsumed }
|
|
1910
|
+
} = await rpc.simulateTransaction(base64EncodedTransaction, {
|
|
1911
|
+
encoding: "base64",
|
|
1912
|
+
sigVerify: false,
|
|
1913
|
+
replaceRecentBlockhash: false,
|
|
1914
|
+
commitment: "confirmed"
|
|
1915
|
+
}).send();
|
|
1916
|
+
return {
|
|
1917
|
+
err,
|
|
1918
|
+
logs: logs ?? [],
|
|
1919
|
+
unitsConsumed: unitsConsumed ?? 0n
|
|
1920
|
+
};
|
|
1921
|
+
}
|
|
1922
|
+
async function signSendAndConfirmTransaction(rpc, payer, instructionsOrPlan, options) {
|
|
1923
|
+
const instructions = Array.isArray(instructionsOrPlan) ? instructionsOrPlan : instructionsOrPlan.instructions;
|
|
1924
|
+
const lookupTables = Array.isArray(instructionsOrPlan) ? options?.lookupTables : options?.lookupTables ?? instructionsOrPlan.lookupTables;
|
|
1925
|
+
const segmentLengths = Array.isArray(instructionsOrPlan) ? void 0 : instructionsOrPlan.segmentLengths;
|
|
1926
|
+
const freshBinSegments = Array.isArray(instructionsOrPlan) ? void 0 : instructionsOrPlan.freshBinSegments;
|
|
1927
|
+
const filteredLuts = lookupTables?.filter((x) => x !== DEFAULT_PUBLIC_KEY);
|
|
1928
|
+
const transactionMessage = await buildTransactionMessage(
|
|
1929
|
+
rpc,
|
|
1930
|
+
payer,
|
|
1931
|
+
instructions,
|
|
1932
|
+
filteredLuts,
|
|
1933
|
+
options?.additionalSigners
|
|
1934
|
+
);
|
|
1935
|
+
const txBytes = measureTxBytes(transactionMessage);
|
|
1936
|
+
const maxUnaugmentedTxBytes = SOLANA_TX_SIZE_LIMIT - BUNDLE_INJECTED_IX_RESERVED_BYTES;
|
|
1937
|
+
const mustSplit = txBytes > maxUnaugmentedTxBytes || options?.forceJitoBundle || !!freshBinSegments?.length;
|
|
1938
|
+
if (mustSplit) {
|
|
1939
|
+
if (options?.sendOversizedAsSequentialTransactions) {
|
|
1940
|
+
return signSendAndConfirmSplitSequentially(
|
|
1941
|
+
rpc,
|
|
1942
|
+
payer,
|
|
1943
|
+
instructions,
|
|
1944
|
+
filteredLuts,
|
|
1945
|
+
options,
|
|
1946
|
+
segmentLengths,
|
|
1947
|
+
freshBinSegments
|
|
1948
|
+
);
|
|
1949
|
+
}
|
|
1950
|
+
return _signSendAndConfirmBundle(
|
|
1951
|
+
rpc,
|
|
1952
|
+
payer,
|
|
1953
|
+
instructions,
|
|
1954
|
+
filteredLuts,
|
|
1955
|
+
options,
|
|
1956
|
+
segmentLengths,
|
|
1957
|
+
freshBinSegments
|
|
1958
|
+
);
|
|
1959
|
+
}
|
|
1960
|
+
const writableAccounts = collectWritableAccounts(instructions);
|
|
1961
|
+
const priorityFeeMicroLamports = await resolvePriorityFeeMicroLamports(
|
|
1962
|
+
rpc,
|
|
1963
|
+
transactionMessage,
|
|
1964
|
+
writableAccounts,
|
|
1965
|
+
options
|
|
1966
|
+
);
|
|
1967
|
+
const simMessage = appendTransactionMessageInstructions(
|
|
1968
|
+
getComputeBudgetInstructions(MAX_COMPUTE_UNIT_LIMIT, priorityFeeMicroLamports),
|
|
1969
|
+
transactionMessage
|
|
1970
|
+
);
|
|
1971
|
+
const simulation = await simulateTransaction(rpc, simMessage);
|
|
1972
|
+
if (simulation.err) {
|
|
1973
|
+
if (!options?.hideFailureInfo) {
|
|
1974
|
+
console.error("Simulation failed:", simulation.err);
|
|
1975
|
+
logProgramLogsLineByLine(simulation.logs, "Simulation logs");
|
|
1976
|
+
}
|
|
1977
|
+
const errStr = JSON.stringify(
|
|
1978
|
+
simulation.err,
|
|
1979
|
+
(_, v) => typeof v === "bigint" ? v.toString() : v
|
|
1980
|
+
);
|
|
1981
|
+
throw new TransactionError(`Transaction simulation failed: ${errStr}`, simulation.logs);
|
|
1982
|
+
}
|
|
1983
|
+
const computeUnits = computeUnitLimitFromSimulation(
|
|
1984
|
+
Number(simulation.unitsConsumed),
|
|
1985
|
+
options?.computeUnitLimitMultiplier ?? DEFAULT_COMPUTE_UNIT_LIMIT_MULTIPLIER
|
|
1986
|
+
);
|
|
1987
|
+
const finalMessage = appendTransactionMessageInstructions(
|
|
1988
|
+
getComputeBudgetInstructions(computeUnits, priorityFeeMicroLamports),
|
|
1989
|
+
transactionMessage
|
|
1990
|
+
);
|
|
1991
|
+
const signedTx = await signTransactionMessageWithSigners(
|
|
1992
|
+
finalMessage
|
|
1993
|
+
);
|
|
1994
|
+
const base64EncodedTransaction = getBase64EncodedWireTransaction2(signedTx);
|
|
1995
|
+
const signature = getSignatureFromTransaction(signedTx);
|
|
1996
|
+
await rpc.sendTransaction(base64EncodedTransaction, {
|
|
1997
|
+
encoding: "base64",
|
|
1998
|
+
skipPreflight: true
|
|
1999
|
+
}).send();
|
|
2000
|
+
try {
|
|
2001
|
+
await confirmTransaction(rpc, signature, "confirmed");
|
|
2002
|
+
options?.onSuccess?.();
|
|
2003
|
+
return signature;
|
|
2004
|
+
} catch (error) {
|
|
2005
|
+
let logs = [];
|
|
2006
|
+
let landedSuccessfully = false;
|
|
2007
|
+
try {
|
|
2008
|
+
const info = await rpc.getTransaction(signature, { commitment: "confirmed", encoding: "base64" }).send();
|
|
2009
|
+
if (info) {
|
|
2010
|
+
logs = info.meta?.logMessages ?? [];
|
|
2011
|
+
if (info.meta?.err == null) {
|
|
2012
|
+
landedSuccessfully = true;
|
|
2013
|
+
}
|
|
2014
|
+
}
|
|
2015
|
+
} catch {
|
|
2016
|
+
}
|
|
2017
|
+
if (landedSuccessfully) {
|
|
2018
|
+
console.warn(
|
|
2019
|
+
`Confirmation polling failed for signature ${signature} but the transaction landed on-chain; treating as success. Reason: ${error instanceof Error ? error.message : String(error)}`
|
|
2020
|
+
);
|
|
2021
|
+
options?.onSuccess?.();
|
|
2022
|
+
return signature;
|
|
2023
|
+
}
|
|
2024
|
+
if (!options?.hideFailureInfo) {
|
|
2025
|
+
console.error("Transaction failed:", error);
|
|
2026
|
+
logProgramLogsLineByLine(logs, "Transaction logs");
|
|
2027
|
+
}
|
|
2028
|
+
throw new TransactionError(`Transaction failed: ${error}`, logs);
|
|
2029
|
+
}
|
|
2030
|
+
}
|
|
2031
|
+
async function signSplitBin(rpc, payer, bin, lookupTables, additionalSigners, blockhash, priorityFeeMicroLamports) {
|
|
2032
|
+
const msg = await buildTransactionMessage(
|
|
2033
|
+
rpc,
|
|
2034
|
+
payer,
|
|
2035
|
+
bin,
|
|
2036
|
+
lookupTables,
|
|
2037
|
+
additionalSigners,
|
|
2038
|
+
blockhash
|
|
2039
|
+
);
|
|
2040
|
+
const finalMsg = appendTransactionMessageInstructions(
|
|
2041
|
+
getComputeBudgetInstructions(MAX_COMPUTE_UNIT_LIMIT, priorityFeeMicroLamports),
|
|
2042
|
+
msg
|
|
2043
|
+
);
|
|
2044
|
+
const signed = await signTransactionMessageWithSigners(finalMsg);
|
|
2045
|
+
return {
|
|
2046
|
+
wireB64: getBase64EncodedWireTransaction2(signed),
|
|
2047
|
+
signature: getSignatureFromTransaction(signed)
|
|
2048
|
+
};
|
|
2049
|
+
}
|
|
2050
|
+
async function _signSendAndConfirmBundle(rpc, payer, instructions, lookupTables, options, segmentLengths, freshBinSegments) {
|
|
2051
|
+
const tipLamports = options?.jitoTipLamports ?? DEFAULT_JITO_TIP_LAMPORTS;
|
|
2052
|
+
if (tipLamports === 0) {
|
|
2053
|
+
throw new TransactionError(
|
|
2054
|
+
"Transaction exceeds the Solana size limit and Jito bundling is disabled. Set jitoTipLamports > 0 to enable bundle fallback."
|
|
2055
|
+
);
|
|
2056
|
+
}
|
|
2057
|
+
const { value: blockhash } = await rpc.getLatestBlockhash({ commitment: "confirmed" }).send();
|
|
2058
|
+
const { bins } = await splitIntoTransactionBins(rpc, payer, instructions, {
|
|
2059
|
+
lookupTables,
|
|
2060
|
+
additionalSigners: options?.additionalSigners,
|
|
2061
|
+
blockhash,
|
|
2062
|
+
reservedBytes: BUNDLE_INJECTED_IX_RESERVED_BYTES,
|
|
2063
|
+
segmentLengths,
|
|
2064
|
+
freshBinSegments
|
|
2065
|
+
});
|
|
2066
|
+
if (bins.length === 0) {
|
|
2067
|
+
throw new TransactionError("Bundle build produced 0 bins; cannot attach Jito tip.");
|
|
2068
|
+
}
|
|
2069
|
+
const messages = [];
|
|
2070
|
+
for (const bin of bins) {
|
|
2071
|
+
messages.push(
|
|
2072
|
+
await buildTransactionMessage(
|
|
2073
|
+
rpc,
|
|
2074
|
+
payer,
|
|
2075
|
+
bin,
|
|
2076
|
+
lookupTables,
|
|
2077
|
+
options?.additionalSigners,
|
|
2078
|
+
blockhash
|
|
2079
|
+
)
|
|
2080
|
+
);
|
|
2081
|
+
}
|
|
2082
|
+
const tipBinIdx = messages.map((m, i) => ({ i, bytes: measureTxBytes(m) })).reduce((a, b) => a.bytes <= b.bytes ? a : b).i;
|
|
2083
|
+
const tipAccount = getRandomTipAccount();
|
|
2084
|
+
const tipIx = buildTipInstruction(payer, tipAccount, tipLamports);
|
|
2085
|
+
messages[tipBinIdx] = appendTransactionMessageInstructions(
|
|
2086
|
+
[tipIx],
|
|
2087
|
+
messages[tipBinIdx]
|
|
2088
|
+
);
|
|
2089
|
+
console.log(
|
|
2090
|
+
`[bundle] attached ${tipLamports} lamport tip to tx[${tipBinIdx}] (smallest of ${messages.length}) \u2192 ${tipAccount}`
|
|
2091
|
+
);
|
|
2092
|
+
const priorityFeeMicroLamports = await Promise.all(
|
|
2093
|
+
messages.map(
|
|
2094
|
+
(message, index) => resolvePriorityFeeMicroLamports(rpc, message, collectWritableAccounts(bins[index]), options)
|
|
2095
|
+
)
|
|
2096
|
+
);
|
|
2097
|
+
const simEncodedTxs = [];
|
|
2098
|
+
for (let i = 0; i < messages.length; i += 1) {
|
|
2099
|
+
const simMsg = appendTransactionMessageInstructions(
|
|
2100
|
+
getComputeBudgetInstructions(MAX_COMPUTE_UNIT_LIMIT, priorityFeeMicroLamports[i]),
|
|
2101
|
+
messages[i]
|
|
2102
|
+
);
|
|
2103
|
+
const compiled = compileTransaction3(simMsg);
|
|
2104
|
+
simEncodedTxs.push(getBase64EncodedWireTransaction2(compiled));
|
|
2105
|
+
}
|
|
2106
|
+
const rpcUrl = getMainnetRpcUrl();
|
|
2107
|
+
const simResult = await simulateBundle(rpcUrl, simEncodedTxs, {
|
|
2108
|
+
replaceRecentBlockhash: false
|
|
2109
|
+
});
|
|
2110
|
+
const failingIdx = simResult.transactionResults.findIndex((r) => r.err != null);
|
|
2111
|
+
if (simResult.summary !== "succeeded" || failingIdx >= 0) {
|
|
2112
|
+
const idx = failingIdx >= 0 ? failingIdx : 0;
|
|
2113
|
+
const failed = simResult.transactionResults[idx];
|
|
2114
|
+
if (!options?.hideFailureInfo) {
|
|
2115
|
+
console.error(`Bundle simulation failed at tx[${idx}] of ${bins.length}.`);
|
|
2116
|
+
console.error("Summary:", JSON.stringify(simResult.summary, null, 2));
|
|
2117
|
+
simResult.transactionResults.forEach((r, i) => {
|
|
2118
|
+
const tag = i === idx ? " \u2190 FAILED" : i < idx ? " (succeeded)" : " (not run)";
|
|
2119
|
+
console.error(`
|
|
2120
|
+
\u2500\u2500 tx[${i}]${tag} (unitsConsumed=${r.unitsConsumed ?? "\u2014"}) \u2500\u2500`);
|
|
2121
|
+
if (r.err != null) console.error(" err:", JSON.stringify(r.err));
|
|
2122
|
+
logProgramLogsLineByLine(r.logs ?? [], `tx[${i}] bundle simulation logs`);
|
|
2123
|
+
});
|
|
2124
|
+
try {
|
|
2125
|
+
const failedSimMsg = appendTransactionMessageInstructions(
|
|
2126
|
+
getComputeBudgetInstructions(MAX_COMPUTE_UNIT_LIMIT, priorityFeeMicroLamports[idx]),
|
|
2127
|
+
messages[idx]
|
|
2128
|
+
);
|
|
2129
|
+
const failedB64 = getBase64EncodedWireTransaction2(compileTransaction3(failedSimMsg));
|
|
2130
|
+
const standalone = await jsonRpcFetchOnce(rpcUrl, "simulateTransaction", [
|
|
2131
|
+
failedB64,
|
|
2132
|
+
{
|
|
2133
|
+
encoding: "base64",
|
|
2134
|
+
sigVerify: false,
|
|
2135
|
+
replaceRecentBlockhash: false,
|
|
2136
|
+
commitment: "confirmed"
|
|
2137
|
+
}
|
|
2138
|
+
]);
|
|
2139
|
+
console.error(
|
|
2140
|
+
`
|
|
2141
|
+
\u2500\u2500 tx[${idx}] standalone simulateTransaction (full logs, no preceding-bin effects) \u2500\u2500`
|
|
2142
|
+
);
|
|
2143
|
+
if (standalone.value.err != null)
|
|
2144
|
+
console.error(
|
|
2145
|
+
" err:",
|
|
2146
|
+
JSON.stringify(
|
|
2147
|
+
standalone.value.err,
|
|
2148
|
+
(_, v) => typeof v === "bigint" ? v.toString() : v
|
|
2149
|
+
)
|
|
2150
|
+
);
|
|
2151
|
+
const logs = standalone.value.logs ?? [];
|
|
2152
|
+
logProgramLogsLineByLine(logs, `tx[${idx}] standalone simulation logs`);
|
|
2153
|
+
} catch (err) {
|
|
2154
|
+
console.error(
|
|
2155
|
+
" (standalone fallback failed:",
|
|
2156
|
+
err instanceof Error ? err.message : String(err),
|
|
2157
|
+
")"
|
|
2158
|
+
);
|
|
2159
|
+
}
|
|
2160
|
+
}
|
|
2161
|
+
const errStr = JSON.stringify(
|
|
2162
|
+
failed?.err ?? simResult.summary,
|
|
2163
|
+
(_, v) => typeof v === "bigint" ? v.toString() : v
|
|
2164
|
+
);
|
|
2165
|
+
throw new TransactionError(
|
|
2166
|
+
`Bundle simulation failed at tx[${idx}]: ${errStr}`,
|
|
2167
|
+
failed?.logs ?? []
|
|
2168
|
+
);
|
|
2169
|
+
}
|
|
2170
|
+
const finalTransactions = [];
|
|
2171
|
+
for (let i = 0; i < messages.length; i += 1) {
|
|
2172
|
+
const measured = simResult.transactionResults[i]?.unitsConsumed;
|
|
2173
|
+
const cu = measured && measured > 0 ? Math.ceil(measured * 1.1) : MAX_COMPUTE_UNIT_LIMIT;
|
|
2174
|
+
const withCu = appendTransactionMessageInstructions(
|
|
2175
|
+
getComputeBudgetInstructions(cu, priorityFeeMicroLamports[i]),
|
|
2176
|
+
messages[i]
|
|
2177
|
+
);
|
|
2178
|
+
const finalMsg = setTransactionMessageLifetimeUsingBlockhash(
|
|
2179
|
+
blockhash,
|
|
2180
|
+
withCu
|
|
2181
|
+
);
|
|
2182
|
+
finalTransactions.push(compileTransaction3(finalMsg));
|
|
2183
|
+
}
|
|
2184
|
+
const signedTransactions = await signTransactionsWithSigners(finalTransactions, [
|
|
2185
|
+
payer,
|
|
2186
|
+
...options?.additionalSigners ?? []
|
|
2187
|
+
]);
|
|
2188
|
+
const base64Txs = signedTransactions.map(getBase64EncodedWireTransaction2);
|
|
2189
|
+
const lastSignature = getSignatureFromTransaction(
|
|
2190
|
+
signedTransactions[signedTransactions.length - 1]
|
|
2191
|
+
);
|
|
2192
|
+
try {
|
|
2193
|
+
console.log(`[bundle] sending via ${redactRpcUrlForLog(rpcUrl)}`);
|
|
2194
|
+
const bundleId = await sendBundle(rpcUrl, base64Txs);
|
|
2195
|
+
await confirmBundle(rpcUrl, bundleId);
|
|
2196
|
+
options?.onSuccess?.();
|
|
2197
|
+
return lastSignature;
|
|
2198
|
+
} catch (error) {
|
|
2199
|
+
if (error instanceof JitoBundleError) {
|
|
2200
|
+
throw new TransactionError(`Jito bundle failed: ${error.message}`);
|
|
2201
|
+
}
|
|
2202
|
+
throw error;
|
|
2203
|
+
}
|
|
2204
|
+
}
|
|
2205
|
+
async function signSendAndConfirmSplitSequentially(rpc, payer, instructions, lookupTables, options, segmentLengths, freshBinSegments) {
|
|
2206
|
+
const { value: splitBlockhash } = await rpc.getLatestBlockhash({ commitment: "confirmed" }).send();
|
|
2207
|
+
const { bins } = await splitIntoTransactionBins(rpc, payer, instructions, {
|
|
2208
|
+
lookupTables,
|
|
2209
|
+
additionalSigners: options?.additionalSigners,
|
|
2210
|
+
blockhash: splitBlockhash,
|
|
2211
|
+
reservedBytes: BUNDLE_INJECTED_IX_RESERVED_BYTES,
|
|
2212
|
+
segmentLengths,
|
|
2213
|
+
freshBinSegments
|
|
2214
|
+
});
|
|
2215
|
+
let lastSignature;
|
|
2216
|
+
for (const [binIndex, bin] of bins.entries()) {
|
|
2217
|
+
const { value: blockhash } = await rpc.getLatestBlockhash({ commitment: "confirmed" }).send();
|
|
2218
|
+
const transactionMessage = await buildTransactionMessage(
|
|
2219
|
+
rpc,
|
|
2220
|
+
payer,
|
|
2221
|
+
bin,
|
|
2222
|
+
lookupTables,
|
|
2223
|
+
options?.additionalSigners,
|
|
2224
|
+
blockhash
|
|
2225
|
+
);
|
|
2226
|
+
const priorityFeeMicroLamports = await resolvePriorityFeeMicroLamports(
|
|
2227
|
+
rpc,
|
|
2228
|
+
transactionMessage,
|
|
2229
|
+
collectWritableAccounts(bin),
|
|
2230
|
+
options
|
|
2231
|
+
);
|
|
2232
|
+
const simMsg = appendTransactionMessageInstructions(
|
|
2233
|
+
getComputeBudgetInstructions(MAX_COMPUTE_UNIT_LIMIT, priorityFeeMicroLamports),
|
|
2234
|
+
transactionMessage
|
|
2235
|
+
);
|
|
2236
|
+
const simulation = await simulateTransaction(rpc, simMsg);
|
|
2237
|
+
if (simulation.err) {
|
|
2238
|
+
if (!options?.hideFailureInfo) {
|
|
2239
|
+
console.error(`Simulation failed for split bin ${binIndex}:`, simulation.err);
|
|
2240
|
+
logProgramLogsLineByLine(simulation.logs, `split bin ${binIndex} simulation logs`);
|
|
2241
|
+
}
|
|
2242
|
+
const errStr = JSON.stringify(
|
|
2243
|
+
simulation.err,
|
|
2244
|
+
(_, v) => typeof v === "bigint" ? v.toString() : v
|
|
2245
|
+
);
|
|
2246
|
+
throw new TransactionError(
|
|
2247
|
+
`Split bin ${binIndex} simulation failed: ${errStr}`,
|
|
2248
|
+
simulation.logs
|
|
2249
|
+
);
|
|
2250
|
+
}
|
|
2251
|
+
const { wireB64, signature } = await signSplitBin(
|
|
2252
|
+
rpc,
|
|
2253
|
+
payer,
|
|
2254
|
+
bin,
|
|
2255
|
+
lookupTables,
|
|
2256
|
+
options?.additionalSigners,
|
|
2257
|
+
blockhash,
|
|
2258
|
+
priorityFeeMicroLamports
|
|
2259
|
+
);
|
|
2260
|
+
await rpc.sendTransaction(wireB64, {
|
|
2261
|
+
encoding: "base64",
|
|
2262
|
+
skipPreflight: true
|
|
2263
|
+
}).send();
|
|
2264
|
+
try {
|
|
2265
|
+
await confirmTransaction(rpc, signature, "confirmed");
|
|
2266
|
+
} catch (error) {
|
|
2267
|
+
const logs = await fetchTransactionLogsWithRetry(rpc, signature);
|
|
2268
|
+
if (!options?.hideFailureInfo) {
|
|
2269
|
+
console.error(`Transaction failed for split bin ${binIndex}:`, signature, error);
|
|
2270
|
+
logProgramLogsLineByLine(logs, `split bin ${binIndex} transaction logs`);
|
|
2271
|
+
}
|
|
2272
|
+
throw new TransactionError(`Transaction failed: ${error}`, logs);
|
|
2273
|
+
}
|
|
2274
|
+
lastSignature = signature;
|
|
2275
|
+
}
|
|
2276
|
+
options?.onSuccess?.();
|
|
2277
|
+
return lastSignature;
|
|
2278
|
+
}
|
|
2279
|
+
async function fetchTransactionLogsWithRetry(rpc, signature) {
|
|
2280
|
+
for (let attempt = 0; attempt < 10; attempt += 1) {
|
|
2281
|
+
try {
|
|
2282
|
+
const info = await rpc.getTransaction(signature, { commitment: "confirmed", encoding: "base64" }).send();
|
|
2283
|
+
const logs = info?.meta?.logMessages ?? [];
|
|
2284
|
+
if (logs.length > 0) return logs;
|
|
2285
|
+
} catch {
|
|
2286
|
+
}
|
|
2287
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
2288
|
+
}
|
|
2289
|
+
return [];
|
|
2290
|
+
}
|
|
2291
|
+
async function confirmTransaction(rpc, signature, commitment, timeoutMs = 6e4) {
|
|
2292
|
+
const startTime = Date.now();
|
|
2293
|
+
const pollIntervalMs = 500;
|
|
2294
|
+
while (Date.now() - startTime < timeoutMs) {
|
|
2295
|
+
let status = null;
|
|
2296
|
+
try {
|
|
2297
|
+
const response = await rpc.getSignatureStatuses([signature]).send();
|
|
2298
|
+
status = response.value[0];
|
|
2299
|
+
} catch (err) {
|
|
2300
|
+
if (!isTransientNetworkError(err)) throw err;
|
|
2301
|
+
}
|
|
2302
|
+
if (status !== null) {
|
|
2303
|
+
if (status.err) {
|
|
2304
|
+
const errStr = JSON.stringify(
|
|
2305
|
+
status.err,
|
|
2306
|
+
(_, v) => typeof v === "bigint" ? v.toString() : v
|
|
2307
|
+
);
|
|
2308
|
+
throw new Error(`Transaction failed: ${errStr}`);
|
|
2309
|
+
}
|
|
2310
|
+
const confirmationStatus = status.confirmationStatus;
|
|
2311
|
+
if (confirmationStatus === commitment || commitment === "processed" && confirmationStatus || commitment === "confirmed" && (confirmationStatus === "confirmed" || confirmationStatus === "finalized") || commitment === "finalized" && confirmationStatus === "finalized") {
|
|
2312
|
+
return;
|
|
2313
|
+
}
|
|
2314
|
+
}
|
|
2315
|
+
await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
|
|
2316
|
+
}
|
|
2317
|
+
throw new Error(`Transaction confirmation timeout after ${timeoutMs}ms`);
|
|
2318
|
+
}
|
|
2319
|
+
|
|
2320
|
+
// ../../shared/common/src/services/baseIxBuilderService.ts
|
|
2321
|
+
var BaseIXBuilderService = class {
|
|
2322
|
+
constructor(context) {
|
|
2323
|
+
this.context = context;
|
|
2324
|
+
}
|
|
2325
|
+
};
|
|
2326
|
+
|
|
2327
|
+
// ../../shared/common/src/services/swap/swapRouting.ts
|
|
2328
|
+
function swapClientCanRoute(client, inputMint, outputMint) {
|
|
2329
|
+
if (inputMint === outputMint) {
|
|
2330
|
+
return false;
|
|
2331
|
+
}
|
|
2332
|
+
if (client.inputMints.length === 0 && client.outputMints.length === 0) {
|
|
2333
|
+
return true;
|
|
2334
|
+
}
|
|
2335
|
+
if (!client.inputMints.includes(inputMint) || !client.outputMints.includes(outputMint)) {
|
|
2336
|
+
return false;
|
|
2337
|
+
}
|
|
2338
|
+
if (client.routeAnchorMints.length === 0) {
|
|
2339
|
+
return true;
|
|
2340
|
+
}
|
|
2341
|
+
return client.routeAnchorMints.some((m) => m === inputMint || m === outputMint);
|
|
2342
|
+
}
|
|
2343
|
+
|
|
2344
|
+
// ../../shared/oracle-service/src/constants/pyth.ts
|
|
2345
|
+
import { address as address5 } from "@solana/kit";
|
|
2346
|
+
var PYTH_FEEDS = {
|
|
2347
|
+
// Standard assets
|
|
2348
|
+
SOL: {
|
|
2349
|
+
account: address5("7UVimffxr9ow1uXYxsr4LHAcV58mLzhmwaeKvJ1pjLiE"),
|
|
2350
|
+
feedId: "ef0d8b6fda2ceba41da15d4095d1da392a0d2f8ed0c6c7bc0f4cfac8c280b56d"
|
|
2351
|
+
},
|
|
2352
|
+
WETH: {
|
|
2353
|
+
account: address5("42amVS4KgzR9rA28tkVYqVXjq9Qa8dcZQMbH5EYFX6XC"),
|
|
2354
|
+
feedId: "ff61491a931112ddf1bd8147cd1b641375f79f5825126d665480874634fd0ace"
|
|
2355
|
+
},
|
|
2356
|
+
WBTC: {
|
|
2357
|
+
account: address5("9gNX5vguzarZZPjTnE1hWze3s6UsZ7dsU3UnAmKPnMHG"),
|
|
2358
|
+
feedId: "c9d8b075a5c69303365ae23633d4e085199bf5c520a3b90fed1322a0342ffc33"
|
|
2359
|
+
},
|
|
2360
|
+
CBBTC: {
|
|
2361
|
+
account: address5("4cSM2e6rvbGQUFiJbqytoVMi5GgghSMr8LwVrT9VPSPo"),
|
|
2362
|
+
feedId: "e62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43"
|
|
2363
|
+
},
|
|
2364
|
+
JLP: {
|
|
2365
|
+
account: address5("2TTGSRSezqFzeLUH8JwRUbtN66XLLaymfYsWRTMjfiMw"),
|
|
2366
|
+
feedId: "c811abc82b4bad1f9bd711a2773ccaa935b03ecef974236942cec5e0eb845a3a"
|
|
2367
|
+
},
|
|
2368
|
+
SPYx: {
|
|
2369
|
+
account: address5("9owhtgrdLiUMAH9JKxYFt5pUY4Luy4EzzLhdcWPVuDyy"),
|
|
2370
|
+
feedId: "19e09bb805456ada3979a7d1cbb4b6d63babc3a0f8e8a9509f68afa5c4c11cd5"
|
|
2371
|
+
},
|
|
2372
|
+
QQQx: {
|
|
2373
|
+
account: address5("EwssJrQ7UVz6itHEaQQsKWikhZ3iHddyxRhmR7pTvwt5"),
|
|
2374
|
+
feedId: "9695e2b96ea7b3859da9ed25b7a46a920a776e2fdae19a7bcfdf2b219230452d"
|
|
2375
|
+
},
|
|
2376
|
+
// LSTs
|
|
2377
|
+
JupSOL: {
|
|
2378
|
+
account: address5("D7UqeBmCEmhGXGYfi2y9RfoCa7t1Xw5iZLBeYZ3sxFSe"),
|
|
2379
|
+
feedId: "f8d8d6b6c866c8b2624fb5b679ae846738725e5fc887fa8e927c8d8645018a2b"
|
|
2380
|
+
},
|
|
2381
|
+
// Stablecoins
|
|
2382
|
+
USDC: {
|
|
2383
|
+
account: address5("Dpw1EAVrSB1ibxiDQyTAW6Zip3J4Btk2x4SgApQCeFbX"),
|
|
2384
|
+
feedId: "eaa020c61cc479712813461ce153894a96a6c00b21ed0cfc2798d1f9a9e9c94a"
|
|
2385
|
+
},
|
|
2386
|
+
USDT: {
|
|
2387
|
+
account: address5("HT2PLQBcG5EiCcNSaMHAjSgd9F98ecpATbk4Sk5oYuM"),
|
|
2388
|
+
feedId: "2b89b9dc8fdf9f34709a5b106b472f0f39bb6ca9ce04b0fd7f2e971688e2e53b"
|
|
2389
|
+
},
|
|
2390
|
+
CASH: {
|
|
2391
|
+
account: address5("F23Xi7VQw1pdre26VmuKnjRcDcrhpqGtHkGdKdSdbM8w"),
|
|
2392
|
+
feedId: "df3320ef0f4617337b8dbb924f2aaa4f9db08f522a5435b44f9066c1ac4c7f95"
|
|
2393
|
+
},
|
|
2394
|
+
PYUSD: {
|
|
2395
|
+
account: address5("9zXQxpYH3kYhtoybmZfUNNCRVuud7fY9jswTg1hLyT8k"),
|
|
2396
|
+
feedId: "0xc1da1b73d7f01e7ddd54b3766cf7fcd644395ad14f70aa706ec5384c59e76692"
|
|
2397
|
+
},
|
|
2398
|
+
USDG: {
|
|
2399
|
+
account: address5("6JkZmXGgWnzsyTQaqRARzP64iFYnpMNT4siiuUDUaB8s"),
|
|
2400
|
+
feedId: "0xdaa58c6a3ce7d4b9c46c32a6e646012c17c4a2b24c08dd8c5e476118b855a7da"
|
|
2401
|
+
},
|
|
2402
|
+
USDS: {
|
|
2403
|
+
account: address5("DyYBBWEi9xZvgNAeMDCiFnmC1U9gqgVsJDXkL5WETpoX"),
|
|
2404
|
+
feedId: "0x77f0971af11cc8bac224917275c1bf55f2319ed5c654a1ca955c82fa2d297ea1"
|
|
2405
|
+
},
|
|
2406
|
+
// Yield bearing assets
|
|
2407
|
+
PST: {
|
|
2408
|
+
account: address5("CBGwQddTeYn3KdvxGWtU95fqCcavzHK9XPFBLENDF5JR"),
|
|
2409
|
+
feedId: "675e36f84a6be779ed793c71eb5c03151e1866c125767f46933626e0610af84d"
|
|
2410
|
+
}
|
|
2411
|
+
};
|
|
2412
|
+
|
|
2413
|
+
// ../../shared/perena-helpers/src/constants.ts
|
|
2414
|
+
import { address as address6 } from "@solana/kit";
|
|
2415
|
+
var PERENA_PROGRAM_ID = address6("save8RQVPMWNTzU18t3GBvBkN9hT7jsGjiCQ28FpD9H");
|
|
2416
|
+
|
|
2417
|
+
// ../../shared/perena-helpers/src/client.ts
|
|
2418
|
+
import { BN as BN3 } from "@anchor-lang/core";
|
|
2419
|
+
import { PublicKey as PublicKey3 } from "@solana/web3.js";
|
|
2420
|
+
import {
|
|
2421
|
+
UsdStarClient,
|
|
2422
|
+
BankinecoAction
|
|
2423
|
+
} from "@perena/bankineco-sdk";
|
|
2424
|
+
import { ASSOCIATED_TOKEN_PROGRAM_ADDRESS as ASSOCIATED_TOKEN_PROGRAM_ADDRESS2 } from "@solana-program/token";
|
|
2425
|
+
import { SYSTEM_PROGRAM_ADDRESS as SYSTEM_PROGRAM_ADDRESS3 } from "@solana-program/system";
|
|
2426
|
+
|
|
2427
|
+
// ../../shared/perena-helpers/src/cpi/mint.ts
|
|
2428
|
+
function getPerenaMintArgs(data) {
|
|
2429
|
+
const buf = Buffer.alloc(16);
|
|
2430
|
+
buf.writeBigUInt64LE(BigInt(data.amountYieldingDeposit.toString()), 0);
|
|
2431
|
+
buf.writeBigUInt64LE(BigInt(data.minBankMintMinted.toString()), 8);
|
|
2432
|
+
return buf;
|
|
2433
|
+
}
|
|
2434
|
+
|
|
2435
|
+
// ../../shared/perena-helpers/src/cpi/burn.ts
|
|
2436
|
+
function getPerenaBurnArgs(data) {
|
|
2437
|
+
const buf = Buffer.alloc(16);
|
|
2438
|
+
buf.writeBigUInt64LE(BigInt(data.amountToBurn.toString()), 0);
|
|
2439
|
+
buf.writeBigUInt64LE(BigInt(data.minimumYieldingWithdrawn.toString()), 8);
|
|
2440
|
+
return buf;
|
|
2441
|
+
}
|
|
2442
|
+
|
|
2443
|
+
// ../../shared/perena-helpers/src/cpi/requestUnstake.ts
|
|
2444
|
+
function getPerenaRequestUnstakeArgs(data) {
|
|
2445
|
+
const sharesBytes = numToU64Bytes(data.shares);
|
|
2446
|
+
const buf = Buffer.alloc(9);
|
|
2447
|
+
Buffer.from(sharesBytes).copy(buf, 0);
|
|
2448
|
+
buf.writeUInt8(data.queueId, 8);
|
|
2449
|
+
return buf;
|
|
2450
|
+
}
|
|
2451
|
+
|
|
2452
|
+
// ../../shared/perena-helpers/src/client.ts
|
|
2453
|
+
var ACTIVE_WITHDRAWAL_QUEUES_CACHE_CATEGORY = "activeWithdrawalQueues";
|
|
2454
|
+
var PerenaClient = class {
|
|
2455
|
+
/**
|
|
2456
|
+
* Creates a new Perena client.
|
|
2457
|
+
*
|
|
2458
|
+
* @param rpcUrl - Solana RPC URL
|
|
2459
|
+
*/
|
|
2460
|
+
constructor(rpcUrl) {
|
|
2461
|
+
this.sdkClient = UsdStarClient.new({
|
|
2462
|
+
env: "prod",
|
|
2463
|
+
rpcUrl
|
|
2464
|
+
});
|
|
2465
|
+
this.cache = new DataCache({
|
|
2466
|
+
defaultTtlMs: 6e4 * 5
|
|
2467
|
+
// 5 minute default
|
|
2468
|
+
});
|
|
2469
|
+
const usdStar = mints.get("USD*");
|
|
2470
|
+
if (!usdStar) {
|
|
2471
|
+
throw new Error("USD* mint not found in registry");
|
|
2472
|
+
}
|
|
2473
|
+
this.bankMint = usdStar.address;
|
|
2474
|
+
const usdStarJ = mints.get("USD*-J");
|
|
2475
|
+
if (!usdStarJ) {
|
|
2476
|
+
throw new Error("USD*-J mint not found in registry");
|
|
2477
|
+
}
|
|
2478
|
+
this.juniorMint = usdStarJ.address;
|
|
2479
|
+
const yieldingMints = Object.keys(this.sdkClient.idleVaultIndices);
|
|
2480
|
+
const routable = Object.freeze([this.bankMint, this.juniorMint, ...yieldingMints]);
|
|
2481
|
+
this.inputMints = routable;
|
|
2482
|
+
this.outputMints = routable;
|
|
2483
|
+
this.routeAnchorMints = Object.freeze([this.bankMint, this.juniorMint]);
|
|
2484
|
+
}
|
|
2485
|
+
/**
|
|
2486
|
+
* Get mints that can directly mint USD*.
|
|
2487
|
+
*/
|
|
2488
|
+
async getSupportedSourceMints() {
|
|
2489
|
+
return Object.keys(this.sdkClient.idleVaultIndices).map((key) => key);
|
|
2490
|
+
}
|
|
2491
|
+
/**
|
|
2492
|
+
* Get current protocol info for a source mint.
|
|
2493
|
+
* @param sourceMint - The source mint to get info for (i.e. USDC, USDT, etc.)
|
|
2494
|
+
* @returns Protocol info including fees and limits
|
|
2495
|
+
* @throws Error if sourceMint is not supported by Perena
|
|
2496
|
+
*/
|
|
2497
|
+
async getProtocolInfo(sourceMint) {
|
|
2498
|
+
const supportedSourceMints = await this.getSupportedSourceMints();
|
|
2499
|
+
if (!supportedSourceMints.includes(sourceMint)) {
|
|
2500
|
+
throw new Error(`Source mint ${sourceMint} is not supported by Perena`);
|
|
2501
|
+
}
|
|
2502
|
+
const { data } = await this.cache.getDataOrThrow(
|
|
2503
|
+
async () => {
|
|
2504
|
+
const vault = this.sdkClient.getVault(new PublicKey3(sourceMint));
|
|
2505
|
+
const vaultInfo = await this.sdkClient.bankineco.pg.account.vaultGenState.fetch(vault);
|
|
2506
|
+
return {
|
|
2507
|
+
sourceMint,
|
|
2508
|
+
mintFeeBps: vaultInfo.config.mintingFeeBps,
|
|
2509
|
+
redemptionFeeBps: vaultInfo.config.burningFeeBps,
|
|
2510
|
+
depositLimit: BigInt(0),
|
|
2511
|
+
redemptionLimit: BigInt(vaultInfo.accounting.yieldingReserveAmount.toString())
|
|
2512
|
+
};
|
|
2513
|
+
},
|
|
2514
|
+
"yieldProtocolInfo",
|
|
2515
|
+
sourceMint
|
|
2516
|
+
);
|
|
2517
|
+
return data;
|
|
2518
|
+
}
|
|
2519
|
+
/**
|
|
2520
|
+
* Get the latest USD* price in UI units (e.g. dollars).
|
|
2521
|
+
*
|
|
2522
|
+
* @returns The current bank mint price as a number
|
|
2523
|
+
*/
|
|
2524
|
+
async getLatestBankMintUiPrice() {
|
|
2525
|
+
const { data } = await this.cache.getDataOrThrow(
|
|
2526
|
+
() => this.sdkClient.latestBankMintUiPrice(),
|
|
2527
|
+
"bankMintUiPrice",
|
|
2528
|
+
"latest"
|
|
2529
|
+
);
|
|
2530
|
+
return data;
|
|
2531
|
+
}
|
|
2532
|
+
/**
|
|
2533
|
+
* Get the latest USD*-J price in UI units (e.g. dollars).
|
|
2534
|
+
*
|
|
2535
|
+
* @returns The current junior mint price as a number
|
|
2536
|
+
*/
|
|
2537
|
+
async getLatestJuniorMintUiPrice() {
|
|
2538
|
+
const { data } = await this.cache.getDataOrThrow(
|
|
2539
|
+
() => this.sdkClient.latestJuniorMintUiPrice(),
|
|
2540
|
+
"juniorMintUiPrice",
|
|
2541
|
+
"latest"
|
|
2542
|
+
);
|
|
2543
|
+
return data;
|
|
2544
|
+
}
|
|
2545
|
+
/**
|
|
2546
|
+
* Size a USD* burn so the routed yielding output (e.g. USDC) is at least
|
|
2547
|
+
* `minYieldingOut` base units, without scanning inputs.
|
|
2548
|
+
*
|
|
2549
|
+
* Perena's `bankMintToYieldingQuote` is linear in the burn amount for fixed
|
|
2550
|
+
* oracles: bank-mint price, yielding price, burn fee bps, and decimal
|
|
2551
|
+
* rescales are all proportional in `amountToBurn`. We take **one** reference
|
|
2552
|
+
* quote at exactly 1.0 bank-mint token (10^decimals base units) to read the
|
|
2553
|
+
* effective `yieldingOut / bankMintIn` rate implied by the current prices,
|
|
2554
|
+
* then `ceil(need * refIn / refOut)` and re-quote once at that input so the
|
|
2555
|
+
* returned {@link PerenaSwapQuote} matches the CPI.
|
|
2556
|
+
*/
|
|
2557
|
+
/**
|
|
2558
|
+
* @deprecated Prefer {@link getQuoteCoveringMinOutput} — same behavior with generic param names.
|
|
2559
|
+
*/
|
|
2560
|
+
async getQuoteCoveringYieldingOut(params) {
|
|
2561
|
+
return this.getQuoteCoveringMinOutput({
|
|
2562
|
+
inputMint: params.inputMint,
|
|
2563
|
+
outputMint: params.outputMint,
|
|
2564
|
+
minOutputAmount: params.minYieldingOut,
|
|
2565
|
+
maxInputAmount: params.maxBankMintIn,
|
|
2566
|
+
slippageBps: params.slippageBps
|
|
2567
|
+
});
|
|
2568
|
+
}
|
|
2569
|
+
async getQuoteCoveringMinOutput(params) {
|
|
2570
|
+
if (params.inputMint !== this.bankMint) {
|
|
2571
|
+
throw new Error("getQuoteCoveringMinOutput only supports burning USD* into a yielding mint");
|
|
2572
|
+
}
|
|
2573
|
+
const need = params.minOutputAmount;
|
|
2574
|
+
if (need <= BigInt(0)) {
|
|
2575
|
+
throw new Error("getQuoteCoveringMinOutput: minOutputAmount must be positive");
|
|
2576
|
+
}
|
|
2577
|
+
const maxIn = params.maxInputAmount;
|
|
2578
|
+
if (maxIn <= BigInt(0)) {
|
|
2579
|
+
throw new Error("getQuoteCoveringMinOutput: maxInputAmount must be positive");
|
|
2580
|
+
}
|
|
2581
|
+
const vault = this.sdkClient.getVault(new PublicKey3(params.outputMint));
|
|
2582
|
+
const refInBn = mints.get("USD*").fromUiAmount(1);
|
|
2583
|
+
const oneBankMint = BigInt(refInBn.toString());
|
|
2584
|
+
const refSdk = await this.sdkClient.bankMintToYieldingQuote(refInBn, vault);
|
|
2585
|
+
const refOut = BigInt(refSdk.amount.toString());
|
|
2586
|
+
if (refOut === BigInt(0)) {
|
|
2587
|
+
throw new Error("Perena reference burn quote returned zero yielding output");
|
|
2588
|
+
}
|
|
2589
|
+
const maxSdk = await this.sdkClient.bankMintToYieldingQuote(new BN3(maxIn.toString()), vault);
|
|
2590
|
+
if (BigInt(maxSdk.amount.toString()) < need) {
|
|
2591
|
+
throw new Error(
|
|
2592
|
+
"Perena: bank mint holding cannot cover the yielding output required for this unwind"
|
|
2593
|
+
);
|
|
2594
|
+
}
|
|
2595
|
+
const scaleInput = (targetOut) => {
|
|
2596
|
+
const numer = targetOut * oneBankMint + refOut - BigInt(1);
|
|
2597
|
+
return numer / refOut;
|
|
2598
|
+
};
|
|
2599
|
+
let inputRaw = scaleInput(need);
|
|
2600
|
+
if (inputRaw > maxIn) {
|
|
2601
|
+
inputRaw = maxIn;
|
|
2602
|
+
}
|
|
2603
|
+
if (inputRaw < BigInt(1)) {
|
|
2604
|
+
inputRaw = BigInt(1);
|
|
2605
|
+
}
|
|
2606
|
+
const slippageBps = params.slippageBps ?? 100;
|
|
2607
|
+
const quoteAt = async (inAmt) => {
|
|
2608
|
+
if (inAmt > BigInt(Number.MAX_SAFE_INTEGER)) {
|
|
2609
|
+
throw new Error("getQuoteCoveringMinOutput: burn input exceeds Number.MAX_SAFE_INTEGER");
|
|
2610
|
+
}
|
|
2611
|
+
return this.getQuote({
|
|
2612
|
+
inputMint: params.inputMint,
|
|
2613
|
+
outputMint: params.outputMint,
|
|
2614
|
+
amount: Number(inAmt),
|
|
2615
|
+
slippageBps
|
|
2616
|
+
});
|
|
2617
|
+
};
|
|
2618
|
+
let quote = await quoteAt(inputRaw);
|
|
2619
|
+
let out = BigInt(quote.outputAmount.toString());
|
|
2620
|
+
if (out < need && inputRaw < maxIn) {
|
|
2621
|
+
inputRaw = (need * inputRaw + out - BigInt(1)) / out;
|
|
2622
|
+
if (inputRaw > maxIn) {
|
|
2623
|
+
inputRaw = maxIn;
|
|
2624
|
+
}
|
|
2625
|
+
quote = await quoteAt(inputRaw);
|
|
2626
|
+
out = BigInt(quote.outputAmount.toString());
|
|
2627
|
+
}
|
|
2628
|
+
if (out < need && inputRaw < maxIn) {
|
|
2629
|
+
inputRaw += BigInt(1);
|
|
2630
|
+
if (inputRaw > maxIn) {
|
|
2631
|
+
inputRaw = maxIn;
|
|
2632
|
+
}
|
|
2633
|
+
quote = await quoteAt(inputRaw);
|
|
2634
|
+
out = BigInt(quote.outputAmount.toString());
|
|
2635
|
+
}
|
|
2636
|
+
if (out < need) {
|
|
2637
|
+
throw new Error(
|
|
2638
|
+
"Perena: sized burn quote still below required yielding output (rounding); try larger holding or refresh oracles"
|
|
2639
|
+
);
|
|
2640
|
+
}
|
|
2641
|
+
return quote;
|
|
2642
|
+
}
|
|
2643
|
+
/**
|
|
2644
|
+
* Get a quote for minting/burning USD* or staking/unstaking USD*-J.
|
|
2645
|
+
*
|
|
2646
|
+
* The operation is determined by the mints:
|
|
2647
|
+
* - outputMint is USD*: mint (yielding → USD*)
|
|
2648
|
+
* - inputMint is USD*: burn (USD* → yielding)
|
|
2649
|
+
* - outputMint is USD*-J: stake (USD* → USD*-J)
|
|
2650
|
+
* - inputMint is USD*-J: unstake (USD*-J → USD* or yielding)
|
|
2651
|
+
*
|
|
2652
|
+
* @param params - Quote parameters
|
|
2653
|
+
* @returns Normalized swap quote
|
|
2654
|
+
* @throws Error if the mint pair is not supported
|
|
2655
|
+
*/
|
|
2656
|
+
async getQuote(params) {
|
|
2657
|
+
const isJuniorInput = params.inputMint === this.juniorMint;
|
|
2658
|
+
const isJuniorOutput = params.outputMint === this.juniorMint;
|
|
2659
|
+
if (isJuniorOutput) {
|
|
2660
|
+
if (params.inputMint !== this.bankMint) {
|
|
2661
|
+
throw new Error("Invalid Perena quote: can only stake USD* into USD*-J");
|
|
2662
|
+
}
|
|
2663
|
+
return this.getStakeQuote(params);
|
|
2664
|
+
}
|
|
2665
|
+
if (isJuniorInput) {
|
|
2666
|
+
return this.getUnstakeQuote(params);
|
|
2667
|
+
}
|
|
2668
|
+
const isMint = params.outputMint === this.bankMint;
|
|
2669
|
+
const isBurn = params.inputMint === this.bankMint;
|
|
2670
|
+
if (!isMint && !isBurn) {
|
|
2671
|
+
throw new Error(
|
|
2672
|
+
"Invalid Perena quote: either inputMint or outputMint must be USD* or USD*-J"
|
|
2673
|
+
);
|
|
2674
|
+
}
|
|
2675
|
+
if (isMint && isBurn) {
|
|
2676
|
+
throw new Error("Invalid Perena quote: cannot swap USD* to USD*");
|
|
2677
|
+
}
|
|
2678
|
+
const yieldingMint = isMint ? params.inputMint : params.outputMint;
|
|
2679
|
+
const yieldingMintPubkey = new PublicKey3(yieldingMint);
|
|
2680
|
+
const vault = this.sdkClient.getVault(yieldingMintPubkey);
|
|
2681
|
+
const amount = new BN3(params.amount);
|
|
2682
|
+
const vaultInfo = await this.sdkClient.bankineco.pg.account.vaultGenState.fetch(vault);
|
|
2683
|
+
const feeBps = isMint ? vaultInfo.config.mintingFeeBps : vaultInfo.config.burningFeeBps;
|
|
2684
|
+
const priceImpactPct = feeBps / 100;
|
|
2685
|
+
if (isMint) {
|
|
2686
|
+
const sdkQuote = await this.sdkClient.yieldingToBankMintQuote(amount, vault);
|
|
2687
|
+
return {
|
|
2688
|
+
inputMint: params.inputMint,
|
|
2689
|
+
outputMint: params.outputMint,
|
|
2690
|
+
inputAmount: BigInt(params.amount),
|
|
2691
|
+
outputAmount: BigInt(sdkQuote.amount.toString()),
|
|
2692
|
+
priceImpactPct,
|
|
2693
|
+
rawQuote: { operation: "mint", yieldingMint, sdkQuote }
|
|
2694
|
+
};
|
|
2695
|
+
} else {
|
|
2696
|
+
const sdkQuote = await this.sdkClient.bankMintToYieldingQuote(amount, vault);
|
|
2697
|
+
return {
|
|
2698
|
+
inputMint: params.inputMint,
|
|
2699
|
+
outputMint: params.outputMint,
|
|
2700
|
+
inputAmount: BigInt(params.amount),
|
|
2701
|
+
outputAmount: BigInt(sdkQuote.amount.toString()),
|
|
2702
|
+
priceImpactPct,
|
|
2703
|
+
rawQuote: { operation: "burn", yieldingMint, sdkQuote }
|
|
2704
|
+
};
|
|
2705
|
+
}
|
|
2706
|
+
}
|
|
2707
|
+
/**
|
|
2708
|
+
* Quote for staking USD* → USD*-J.
|
|
2709
|
+
*
|
|
2710
|
+
* Shares minted = amount × bankMintPrice / sharePrice.
|
|
2711
|
+
* Staking has no fee; the on-chain conversion is deterministic.
|
|
2712
|
+
*/
|
|
2713
|
+
async getStakeQuote(params) {
|
|
2714
|
+
const trancheState = await this.sdkClient.fetchTrancheState(true);
|
|
2715
|
+
const bankState = await this.sdkClient.bankineco.pg.account.bankState.fetch(
|
|
2716
|
+
this.sdkClient.bank
|
|
2717
|
+
);
|
|
2718
|
+
const amount = new BN3(params.amount);
|
|
2719
|
+
const sharesOut = amount.mul(bankState.mint.price).div(trancheState.accounting.sharePrice);
|
|
2720
|
+
return {
|
|
2721
|
+
inputMint: params.inputMint,
|
|
2722
|
+
outputMint: params.outputMint,
|
|
2723
|
+
inputAmount: BigInt(params.amount),
|
|
2724
|
+
outputAmount: BigInt(sharesOut.toString()),
|
|
2725
|
+
priceImpactPct: 0,
|
|
2726
|
+
rawQuote: { operation: "stake" }
|
|
2727
|
+
};
|
|
2728
|
+
}
|
|
2729
|
+
/**
|
|
2730
|
+
* Quote for unstaking USD*-J → USD* or yielding mint.
|
|
2731
|
+
*
|
|
2732
|
+
* Uses `fetchUnstakeFee` with `early: true` because instant unstake
|
|
2733
|
+
* always applies the early fee.
|
|
2734
|
+
*/
|
|
2735
|
+
async getUnstakeQuote(params) {
|
|
2736
|
+
const isToYielding = params.outputMint !== this.bankMint;
|
|
2737
|
+
const targetMintPk = isToYielding ? new PublicKey3(params.outputMint) : void 0;
|
|
2738
|
+
const unstakeFee = await this.sdkClient.fetchUnstakeFee({
|
|
2739
|
+
amount: new BN3(params.amount),
|
|
2740
|
+
early: true,
|
|
2741
|
+
targetMint: targetMintPk
|
|
2742
|
+
});
|
|
2743
|
+
const totalFee = unstakeFee.feeAmount.add(unstakeFee.burningFeeAmount);
|
|
2744
|
+
const grossOutput = unstakeFee.amountAfterFee.add(totalFee);
|
|
2745
|
+
const feePct = grossOutput.isZero() ? 0 : totalFee.toNumber() / grossOutput.toNumber() * 100;
|
|
2746
|
+
return {
|
|
2747
|
+
inputMint: params.inputMint,
|
|
2748
|
+
outputMint: params.outputMint,
|
|
2749
|
+
inputAmount: BigInt(params.amount),
|
|
2750
|
+
outputAmount: BigInt(unstakeFee.amountAfterFee.toString()),
|
|
2751
|
+
priceImpactPct: feePct,
|
|
2752
|
+
rawQuote: {
|
|
2753
|
+
operation: "unstake",
|
|
2754
|
+
targetMint: isToYielding ? params.outputMint : void 0,
|
|
2755
|
+
unstakeFee
|
|
2756
|
+
}
|
|
2757
|
+
};
|
|
2758
|
+
}
|
|
2759
|
+
/**
|
|
2760
|
+
* Get CPI accounts for a Perena instruction.
|
|
2761
|
+
*
|
|
2762
|
+
* Account order matches the IDL for the respective instruction.
|
|
2763
|
+
*
|
|
2764
|
+
* @param quote - Quote from getQuote()
|
|
2765
|
+
* @param userPublicKey - Address that will execute the swap (can be a PDA)
|
|
2766
|
+
* @param options - Options on building the CPI
|
|
2767
|
+
* @returns CPI accounts, program ID, and serialized instruction data
|
|
2768
|
+
*/
|
|
2769
|
+
async getSwapCpiData(quote, userPublicKey, _options) {
|
|
2770
|
+
const { operation } = quote.rawQuote;
|
|
2771
|
+
switch (operation) {
|
|
2772
|
+
case "mint":
|
|
2773
|
+
case "burn":
|
|
2774
|
+
return this.getMintBurnCpiData(quote, userPublicKey);
|
|
2775
|
+
case "stake":
|
|
2776
|
+
return await this.getStakeCpiData(quote, userPublicKey);
|
|
2777
|
+
case "unstake":
|
|
2778
|
+
return await this.getInstantUnstakeCpiData(quote, userPublicKey);
|
|
2779
|
+
case "request_unstake": {
|
|
2780
|
+
const rq = quote.rawQuote;
|
|
2781
|
+
return await this.getRequestUnstakeCpiData({
|
|
2782
|
+
shares: new BN3(quote.inputAmount.toString()),
|
|
2783
|
+
queueId: rq.queueId,
|
|
2784
|
+
userPublicKey,
|
|
2785
|
+
payer: rq.payer,
|
|
2786
|
+
targetMint: rq.targetMint
|
|
2787
|
+
});
|
|
2788
|
+
}
|
|
2789
|
+
case "fulfill_unstake": {
|
|
2790
|
+
const fq = quote.rawQuote;
|
|
2791
|
+
return await this.getFulfillUnstakeCpiData({
|
|
2792
|
+
withdrawalQueue: fq.withdrawalQueue,
|
|
2793
|
+
signer: fq.owner,
|
|
2794
|
+
queuePayer: fq.queuePayer,
|
|
2795
|
+
owner: fq.owner,
|
|
2796
|
+
targetMint: fq.targetMint
|
|
2797
|
+
});
|
|
2798
|
+
}
|
|
2799
|
+
}
|
|
2800
|
+
}
|
|
2801
|
+
/**
|
|
2802
|
+
* Derive the withdrawal queue PDA for a given user and queue slot.
|
|
2803
|
+
*/
|
|
2804
|
+
deriveWithdrawalQueue(user, queueId) {
|
|
2805
|
+
return fromWeb3Pk(
|
|
2806
|
+
this.sdkClient.bankineco.withdrawalQueuePDA(this.sdkClient.bank, new PublicKey3(user), queueId)
|
|
2807
|
+
);
|
|
2808
|
+
}
|
|
2809
|
+
/**
|
|
2810
|
+
* Fetch all active withdrawal queue PDAs owned by `user`.
|
|
2811
|
+
*
|
|
2812
|
+
* "Active" means the queue account exists, is owned by Perena, and currently
|
|
2813
|
+
* holds a non-zero locked amount.
|
|
2814
|
+
*/
|
|
2815
|
+
async getActiveWithdrawalQueues(user) {
|
|
2816
|
+
const { data } = await this.cache.getDataOrThrow(
|
|
2817
|
+
async () => {
|
|
2818
|
+
const userPublicKey = new PublicKey3(user);
|
|
2819
|
+
const queueInfos = await this.sdkClient.fetchAllWithdrawalQueues(userPublicKey);
|
|
2820
|
+
return queueInfos.filter((queueInfo) => queueInfo.amount.gt(new BN3(0))).map((queueInfo) => fromWeb3Pk(queueInfo.address));
|
|
2821
|
+
},
|
|
2822
|
+
ACTIVE_WITHDRAWAL_QUEUES_CACHE_CATEGORY,
|
|
2823
|
+
user
|
|
2824
|
+
);
|
|
2825
|
+
return data;
|
|
2826
|
+
}
|
|
2827
|
+
/**
|
|
2828
|
+
* Cache invalidation descriptor for the active-withdrawal-queues snapshot of
|
|
2829
|
+
* one owner. Use this when a transaction may create, consume, or otherwise
|
|
2830
|
+
* mutate Perena withdrawal queues outside this exact client instance.
|
|
2831
|
+
*/
|
|
2832
|
+
getActiveWithdrawalQueuesCacheInvalidation(owner) {
|
|
2833
|
+
return this.getActiveWithdrawalQueuesInvalidation(owner);
|
|
2834
|
+
}
|
|
2835
|
+
getActiveWithdrawalQueuesInvalidation(owner) {
|
|
2836
|
+
return {
|
|
2837
|
+
client: "perena",
|
|
2838
|
+
dataCache: this.cache,
|
|
2839
|
+
category: ACTIVE_WITHDRAWAL_QUEUES_CACHE_CATEGORY,
|
|
2840
|
+
id: owner
|
|
2841
|
+
};
|
|
2842
|
+
}
|
|
2843
|
+
/**
|
|
2844
|
+
* Build CPI data for mint_w_yielding_gen or burn_for_yielding_gen.
|
|
2845
|
+
*/
|
|
2846
|
+
async getMintBurnCpiData(quote, userPublicKey) {
|
|
2847
|
+
const raw = quote.rawQuote;
|
|
2848
|
+
const isMint = raw.operation === "mint";
|
|
2849
|
+
const action = isMint ? BankinecoAction.Mint : BankinecoAction.Burn;
|
|
2850
|
+
const cpiAccounts = await this.sdkClient.getMintAndBurnCpiAccounts(
|
|
2851
|
+
new PublicKey3(raw.yieldingMint),
|
|
2852
|
+
action,
|
|
2853
|
+
new PublicKey3(userPublicKey)
|
|
2854
|
+
);
|
|
2855
|
+
const accounts = [
|
|
2856
|
+
toCustomAccountMeta(userPublicKey, false, void 0, false),
|
|
2857
|
+
toCustomAccountMetaFromWeb3AccountMeta(cpiAccounts.bankState),
|
|
2858
|
+
toCustomAccountMetaFromWeb3AccountMeta(cpiAccounts.vaultState),
|
|
2859
|
+
toCustomAccountMetaFromWeb3AccountMeta(cpiAccounts.oracleState),
|
|
2860
|
+
toCustomAccountMetaFromWeb3AccountMeta(cpiAccounts.yieldingMint),
|
|
2861
|
+
toCustomAccountMetaFromWeb3AccountMeta(cpiAccounts.bankMint),
|
|
2862
|
+
toCustomAccountMetaFromWeb3AccountMeta(cpiAccounts.yieldingUserTa),
|
|
2863
|
+
{
|
|
2864
|
+
...toCustomAccountMetaFromWeb3AccountMeta(cpiAccounts.bankMintUserTa),
|
|
2865
|
+
isRequiredAta: {
|
|
2866
|
+
mint: fromWeb3Pk(cpiAccounts.bankMint.pubkey),
|
|
2867
|
+
owner: userPublicKey,
|
|
2868
|
+
tokenProgram: mints.get("USD*").tokenProgram
|
|
2869
|
+
}
|
|
2870
|
+
},
|
|
2871
|
+
toCustomAccountMetaFromWeb3AccountMeta(cpiAccounts.yieldingVaultAta),
|
|
2872
|
+
toCustomAccountMetaFromWeb3AccountMeta(cpiAccounts.teamState),
|
|
2873
|
+
toCustomAccountMetaFromWeb3AccountMeta(cpiAccounts.feeTeamAta),
|
|
2874
|
+
toCustomAccountMetaFromWeb3AccountMeta(cpiAccounts.systemProgram),
|
|
2875
|
+
toCustomAccountMetaFromWeb3AccountMeta(cpiAccounts.tokenProgram),
|
|
2876
|
+
toCustomAccountMetaFromWeb3AccountMeta(cpiAccounts.yieldingMintProgram),
|
|
2877
|
+
toCustomAccountMetaFromWeb3AccountMeta(cpiAccounts.associatedTokenProgram),
|
|
2878
|
+
...(cpiAccounts.remainingAccounts ?? []).map(
|
|
2879
|
+
(meta) => toCustomAccountMeta(
|
|
2880
|
+
meta.pubkey.toBase58(),
|
|
2881
|
+
meta.isWritable,
|
|
2882
|
+
void 0,
|
|
2883
|
+
meta.isSigner
|
|
2884
|
+
)
|
|
2885
|
+
)
|
|
2886
|
+
];
|
|
2887
|
+
return {
|
|
2888
|
+
cpiType: isMint ? CpiTypes.PERENA_MINT : CpiTypes.PERENA_BURN,
|
|
2889
|
+
accounts,
|
|
2890
|
+
programId: PERENA_PROGRAM_ID,
|
|
2891
|
+
data: isMint ? getPerenaMintArgs({
|
|
2892
|
+
amountYieldingDeposit: quote.inputAmount,
|
|
2893
|
+
minBankMintMinted: quote.outputAmount
|
|
2894
|
+
}) : getPerenaBurnArgs({
|
|
2895
|
+
amountToBurn: quote.inputAmount,
|
|
2896
|
+
minimumYieldingWithdrawn: quote.outputAmount
|
|
2897
|
+
})
|
|
2898
|
+
};
|
|
2899
|
+
}
|
|
2900
|
+
/**
|
|
2901
|
+
* Build CPI data for stake_junior.
|
|
2902
|
+
*
|
|
2903
|
+
* Account order matches the IDL:
|
|
2904
|
+
* user, tranche_state, bank_state, bank_mint, junior_mint,
|
|
2905
|
+
* user_bank_mint_ata, user_junior_mint_ata, junior_escrow_ata,
|
|
2906
|
+
* system_program, token_program, associated_token_program
|
|
2907
|
+
*/
|
|
2908
|
+
async getStakeCpiData(quote, userPublicKey) {
|
|
2909
|
+
const userPk = new PublicKey3(userPublicKey);
|
|
2910
|
+
const trancheAccounts = await this.sdkClient.getStakeCpiAccounts(userPk);
|
|
2911
|
+
const { bankMint, juniorMint, tokenProgram } = trancheAccounts;
|
|
2912
|
+
const userBankMintAta = await getAtaAddress(
|
|
2913
|
+
fromWeb3Pk(bankMint),
|
|
2914
|
+
userPublicKey,
|
|
2915
|
+
fromWeb3Pk(tokenProgram)
|
|
2916
|
+
);
|
|
2917
|
+
const userJuniorMintAta = await getAtaAddress(
|
|
2918
|
+
fromWeb3Pk(juniorMint),
|
|
2919
|
+
userPublicKey,
|
|
2920
|
+
fromWeb3Pk(tokenProgram)
|
|
2921
|
+
);
|
|
2922
|
+
const accounts = [
|
|
2923
|
+
toCustomAccountMeta(userPublicKey, true, void 0, false),
|
|
2924
|
+
toCustomAccountMeta(fromWeb3Pk(trancheAccounts.trancheState), true),
|
|
2925
|
+
toCustomAccountMeta(fromWeb3Pk(trancheAccounts.bankState)),
|
|
2926
|
+
toCustomAccountMeta(fromWeb3Pk(bankMint)),
|
|
2927
|
+
toCustomAccountMeta(fromWeb3Pk(juniorMint), true),
|
|
2928
|
+
toCustomAccountMeta(userBankMintAta, true),
|
|
2929
|
+
{
|
|
2930
|
+
...toCustomAccountMeta(userJuniorMintAta, true),
|
|
2931
|
+
isRequiredAta: {
|
|
2932
|
+
mint: this.juniorMint,
|
|
2933
|
+
owner: userPublicKey,
|
|
2934
|
+
tokenProgram: mints.get("USD*-J").tokenProgram
|
|
2935
|
+
}
|
|
2936
|
+
},
|
|
2937
|
+
toCustomAccountMeta(fromWeb3Pk(trancheAccounts.juniorEscrowAta), true),
|
|
2938
|
+
toCustomAccountMeta(SYSTEM_PROGRAM_ADDRESS3),
|
|
2939
|
+
toCustomAccountMeta(fromWeb3Pk(tokenProgram)),
|
|
2940
|
+
toCustomAccountMeta(ASSOCIATED_TOKEN_PROGRAM_ADDRESS2)
|
|
2941
|
+
];
|
|
2942
|
+
return {
|
|
2943
|
+
cpiType: CpiTypes.PERENA_STAKE,
|
|
2944
|
+
accounts,
|
|
2945
|
+
programId: PERENA_PROGRAM_ID,
|
|
2946
|
+
data: numToU64Bytes(quote.inputAmount)
|
|
2947
|
+
};
|
|
2948
|
+
}
|
|
2949
|
+
/**
|
|
2950
|
+
* Build CPI data for instant_unstake_junior.
|
|
2951
|
+
*
|
|
2952
|
+
* Account order matches the IDL:
|
|
2953
|
+
* user, tranche_state, bank_state, bank_mint, target_mint, junior_mint,
|
|
2954
|
+
* user_junior_mint_ata, owner_bank_mint_ata, junior_escrow_ata,
|
|
2955
|
+
* locked_junior_shares_ata, token_program,
|
|
2956
|
+
* [vault_state, vault_oracle_state, vault_team_state, yielding_mint,
|
|
2957
|
+
* yielding_vault_ata, owner_yielding_ta, vault_fee_team_ata,
|
|
2958
|
+
* yielding_mint_program] (optional, when unstaking to a yielding mint)
|
|
2959
|
+
*/
|
|
2960
|
+
async getInstantUnstakeCpiData(quote, userPublicKey) {
|
|
2961
|
+
const raw = quote.rawQuote;
|
|
2962
|
+
const userPk = new PublicKey3(userPublicKey);
|
|
2963
|
+
const targetMintPk = raw.targetMint ? new PublicKey3(raw.targetMint) : void 0;
|
|
2964
|
+
const trancheAccounts = await this.sdkClient.getUnstakeCpiAccounts(userPk, targetMintPk);
|
|
2965
|
+
const { bankMint, juniorMint, tokenProgram } = trancheAccounts;
|
|
2966
|
+
const userJuniorMintAta = await getAtaAddress(
|
|
2967
|
+
fromWeb3Pk(juniorMint),
|
|
2968
|
+
userPublicKey,
|
|
2969
|
+
fromWeb3Pk(tokenProgram)
|
|
2970
|
+
);
|
|
2971
|
+
const ownerBankMintAta = await getAtaAddress(
|
|
2972
|
+
fromWeb3Pk(bankMint),
|
|
2973
|
+
userPublicKey,
|
|
2974
|
+
fromWeb3Pk(tokenProgram)
|
|
2975
|
+
);
|
|
2976
|
+
const targetMintAddress = raw.targetMint ?? this.bankMint;
|
|
2977
|
+
const accounts = [
|
|
2978
|
+
toCustomAccountMeta(userPublicKey, false, void 0, false),
|
|
2979
|
+
toCustomAccountMeta(fromWeb3Pk(trancheAccounts.trancheState), true),
|
|
2980
|
+
toCustomAccountMeta(fromWeb3Pk(trancheAccounts.bankState), true),
|
|
2981
|
+
toCustomAccountMeta(fromWeb3Pk(bankMint), true),
|
|
2982
|
+
toCustomAccountMeta(targetMintAddress),
|
|
2983
|
+
toCustomAccountMeta(fromWeb3Pk(juniorMint), true),
|
|
2984
|
+
toCustomAccountMeta(userJuniorMintAta, true),
|
|
2985
|
+
{
|
|
2986
|
+
...toCustomAccountMeta(ownerBankMintAta, true),
|
|
2987
|
+
isRequiredAta: {
|
|
2988
|
+
mint: fromWeb3Pk(bankMint),
|
|
2989
|
+
owner: userPublicKey,
|
|
2990
|
+
tokenProgram: mints.get("USD*").tokenProgram
|
|
2991
|
+
}
|
|
2992
|
+
},
|
|
2993
|
+
toCustomAccountMeta(fromWeb3Pk(trancheAccounts.juniorEscrowAta), true),
|
|
2994
|
+
toCustomAccountMeta(fromWeb3Pk(trancheAccounts.lockedJuniorSharesAta), true),
|
|
2995
|
+
toCustomAccountMeta(fromWeb3Pk(tokenProgram))
|
|
2996
|
+
];
|
|
2997
|
+
this.pushYieldingRedemptionAccounts(accounts, trancheAccounts, userPublicKey);
|
|
2998
|
+
return {
|
|
2999
|
+
cpiType: CpiTypes.PERENA_INSTANT_UNSTAKE,
|
|
3000
|
+
accounts,
|
|
3001
|
+
programId: PERENA_PROGRAM_ID,
|
|
3002
|
+
data: numToU64Bytes(quote.inputAmount)
|
|
3003
|
+
};
|
|
3004
|
+
}
|
|
3005
|
+
/**
|
|
3006
|
+
* Build CPI data for request_unstake_junior.
|
|
3007
|
+
*
|
|
3008
|
+
* Account order matches the IDL:
|
|
3009
|
+
* user, payer, withdrawal_queue, tranche_state, bank_state, bank_mint,
|
|
3010
|
+
* target_mint, junior_mint, user_junior_mint_ata, locked_junior_shares_ata,
|
|
3011
|
+
* system_program, token_program
|
|
3012
|
+
*/
|
|
3013
|
+
async getRequestUnstakeCpiData(params) {
|
|
3014
|
+
const userPk = new PublicKey3(params.userPublicKey);
|
|
3015
|
+
const targetMintPk = params.targetMint ? new PublicKey3(params.targetMint) : void 0;
|
|
3016
|
+
const trancheAccounts = await this.sdkClient.getUnstakeCpiAccounts(userPk, targetMintPk);
|
|
3017
|
+
const { bankMint, juniorMint, tokenProgram } = trancheAccounts;
|
|
3018
|
+
const userJuniorMintAta = await getAtaAddress(
|
|
3019
|
+
fromWeb3Pk(juniorMint),
|
|
3020
|
+
params.userPublicKey,
|
|
3021
|
+
fromWeb3Pk(tokenProgram)
|
|
3022
|
+
);
|
|
3023
|
+
const targetMintAddress = params.targetMint ?? this.bankMint;
|
|
3024
|
+
const withdrawalQueue = this.deriveWithdrawalQueue(params.userPublicKey, params.queueId);
|
|
3025
|
+
const accounts = [
|
|
3026
|
+
toCustomAccountMeta(params.userPublicKey, false, void 0, false),
|
|
3027
|
+
toCustomAccountMeta(params.payer, true, void 0, true),
|
|
3028
|
+
toCustomAccountMeta(withdrawalQueue, true),
|
|
3029
|
+
toCustomAccountMeta(fromWeb3Pk(trancheAccounts.trancheState)),
|
|
3030
|
+
toCustomAccountMeta(fromWeb3Pk(trancheAccounts.bankState)),
|
|
3031
|
+
toCustomAccountMeta(fromWeb3Pk(bankMint)),
|
|
3032
|
+
toCustomAccountMeta(targetMintAddress),
|
|
3033
|
+
toCustomAccountMeta(fromWeb3Pk(juniorMint)),
|
|
3034
|
+
toCustomAccountMeta(userJuniorMintAta, true),
|
|
3035
|
+
toCustomAccountMeta(fromWeb3Pk(trancheAccounts.lockedJuniorSharesAta), true),
|
|
3036
|
+
toCustomAccountMeta(SYSTEM_PROGRAM_ADDRESS3),
|
|
3037
|
+
toCustomAccountMeta(fromWeb3Pk(tokenProgram))
|
|
3038
|
+
];
|
|
3039
|
+
return {
|
|
3040
|
+
cpiType: CpiTypes.PERENA_REQUEST_UNSTAKE,
|
|
3041
|
+
accounts,
|
|
3042
|
+
programId: PERENA_PROGRAM_ID,
|
|
3043
|
+
data: getPerenaRequestUnstakeArgs({
|
|
3044
|
+
shares: params.shares,
|
|
3045
|
+
queueId: params.queueId
|
|
3046
|
+
}),
|
|
3047
|
+
postSuccessCacheInvalidations: [
|
|
3048
|
+
this.getActiveWithdrawalQueuesInvalidation(params.userPublicKey)
|
|
3049
|
+
]
|
|
3050
|
+
};
|
|
3051
|
+
}
|
|
3052
|
+
/**
|
|
3053
|
+
* Build CPI data for fulfill_unstake_junior.
|
|
3054
|
+
*
|
|
3055
|
+
* Account order matches the IDL:
|
|
3056
|
+
* signer, queue_payer, withdrawal_queue, tranche_state, bank_state,
|
|
3057
|
+
* bank_mint, junior_mint, owner_bank_mint_ata, junior_escrow_ata,
|
|
3058
|
+
* locked_junior_shares_ata, token_program,
|
|
3059
|
+
* [vault_state, vault_oracle_state, vault_team_state, yielding_mint,
|
|
3060
|
+
* yielding_vault_ata, owner_yielding_ta, vault_fee_team_ata,
|
|
3061
|
+
* yielding_mint_program] (optional, when fulfilling to a yielding mint)
|
|
3062
|
+
*/
|
|
3063
|
+
async getFulfillUnstakeCpiData(params) {
|
|
3064
|
+
const ownerPk = new PublicKey3(params.owner);
|
|
3065
|
+
const targetMintPk = params.targetMint ? new PublicKey3(params.targetMint) : void 0;
|
|
3066
|
+
const trancheAccounts = await this.sdkClient.getUnstakeCpiAccounts(ownerPk, targetMintPk);
|
|
3067
|
+
const { bankMint, juniorMint, tokenProgram } = trancheAccounts;
|
|
3068
|
+
const ownerBankMintAta = await getAtaAddress(
|
|
3069
|
+
fromWeb3Pk(bankMint),
|
|
3070
|
+
params.owner,
|
|
3071
|
+
fromWeb3Pk(tokenProgram)
|
|
3072
|
+
);
|
|
3073
|
+
const accounts = [
|
|
3074
|
+
toCustomAccountMeta(params.signer, false, void 0, false),
|
|
3075
|
+
toCustomAccountMeta(params.queuePayer, true),
|
|
3076
|
+
toCustomAccountMeta(params.withdrawalQueue, true),
|
|
3077
|
+
toCustomAccountMeta(fromWeb3Pk(trancheAccounts.trancheState), true),
|
|
3078
|
+
toCustomAccountMeta(fromWeb3Pk(trancheAccounts.bankState), true),
|
|
3079
|
+
toCustomAccountMeta(fromWeb3Pk(bankMint), true),
|
|
3080
|
+
toCustomAccountMeta(fromWeb3Pk(juniorMint), true),
|
|
3081
|
+
{
|
|
3082
|
+
...toCustomAccountMeta(ownerBankMintAta, true),
|
|
3083
|
+
isRequiredAta: {
|
|
3084
|
+
mint: fromWeb3Pk(bankMint),
|
|
3085
|
+
owner: params.owner,
|
|
3086
|
+
tokenProgram: mints.get("USD*").tokenProgram
|
|
3087
|
+
}
|
|
3088
|
+
},
|
|
3089
|
+
toCustomAccountMeta(fromWeb3Pk(trancheAccounts.juniorEscrowAta), true),
|
|
3090
|
+
toCustomAccountMeta(fromWeb3Pk(trancheAccounts.lockedJuniorSharesAta), true),
|
|
3091
|
+
toCustomAccountMeta(fromWeb3Pk(tokenProgram))
|
|
3092
|
+
];
|
|
3093
|
+
this.pushYieldingRedemptionAccounts(accounts, trancheAccounts, params.owner);
|
|
3094
|
+
return {
|
|
3095
|
+
cpiType: CpiTypes.PERENA_FULFILL_UNSTAKE,
|
|
3096
|
+
accounts,
|
|
3097
|
+
programId: PERENA_PROGRAM_ID,
|
|
3098
|
+
data: new Uint8Array(0),
|
|
3099
|
+
postSuccessCacheInvalidations: [this.getActiveWithdrawalQueuesInvalidation(params.owner)]
|
|
3100
|
+
};
|
|
3101
|
+
}
|
|
3102
|
+
/**
|
|
3103
|
+
* Appends the 8 yielding-redemption account slots that `instant_unstake_junior`
|
|
3104
|
+
* and `fulfill_unstake_junior` expect after `token_program`.
|
|
3105
|
+
*
|
|
3106
|
+
* When a yielding mint is involved, real accounts are pushed. Otherwise Anchor
|
|
3107
|
+
* still requires all 8 slots to be present — each set to the program ID as the
|
|
3108
|
+
* `Option<Account>` sentinel for `None`.
|
|
3109
|
+
*/
|
|
3110
|
+
pushYieldingRedemptionAccounts(accounts, trancheAccounts, owner) {
|
|
3111
|
+
const yr = trancheAccounts.yieldingRedemption;
|
|
3112
|
+
if (yr) {
|
|
3113
|
+
accounts.push(
|
|
3114
|
+
toCustomAccountMeta(fromWeb3Pk(yr.vaultState), true),
|
|
3115
|
+
toCustomAccountMeta(fromWeb3Pk(yr.vaultOracleState)),
|
|
3116
|
+
toCustomAccountMeta(fromWeb3Pk(yr.vaultTeamState), true),
|
|
3117
|
+
toCustomAccountMeta(fromWeb3Pk(yr.yieldingMint)),
|
|
3118
|
+
toCustomAccountMeta(fromWeb3Pk(yr.yieldingVaultAta), true),
|
|
3119
|
+
{
|
|
3120
|
+
...toCustomAccountMeta(fromWeb3Pk(yr.ownerYieldingTa), true),
|
|
3121
|
+
isRequiredAta: {
|
|
3122
|
+
mint: fromWeb3Pk(yr.yieldingMint),
|
|
3123
|
+
owner,
|
|
3124
|
+
tokenProgram: fromWeb3Pk(yr.yieldingMintProgram)
|
|
3125
|
+
}
|
|
3126
|
+
},
|
|
3127
|
+
toCustomAccountMeta(fromWeb3Pk(yr.vaultFeeTeamAta), true),
|
|
3128
|
+
toCustomAccountMeta(fromWeb3Pk(yr.yieldingMintProgram))
|
|
3129
|
+
);
|
|
3130
|
+
} else {
|
|
3131
|
+
const sentinel = PERENA_PROGRAM_ID;
|
|
3132
|
+
for (let i = 0; i < 8; i++) {
|
|
3133
|
+
accounts.push(toCustomAccountMeta(sentinel));
|
|
3134
|
+
}
|
|
3135
|
+
}
|
|
3136
|
+
if (trancheAccounts.remainingAccounts) {
|
|
3137
|
+
for (const meta of trancheAccounts.remainingAccounts) {
|
|
3138
|
+
accounts.push(
|
|
3139
|
+
toCustomAccountMeta(
|
|
3140
|
+
meta.pubkey.toBase58(),
|
|
3141
|
+
meta.isWritable,
|
|
3142
|
+
void 0,
|
|
3143
|
+
meta.isSigner
|
|
3144
|
+
)
|
|
3145
|
+
);
|
|
3146
|
+
}
|
|
3147
|
+
}
|
|
3148
|
+
}
|
|
3149
|
+
};
|
|
3150
|
+
|
|
3151
|
+
// ../../shared/perena-helpers/src/utils.ts
|
|
3152
|
+
function getPerenaWithdrawalQueueAddressesFromCpiData(cpiData) {
|
|
3153
|
+
return cpiData.filter(
|
|
3154
|
+
(cpi) => cpi.cpiType === CpiTypes.PERENA_REQUEST_UNSTAKE || cpi.cpiType === CpiTypes.PERENA_FULFILL_UNSTAKE
|
|
3155
|
+
).map((cpi) => cpi.accounts[2]?.address).filter((address9) => address9 !== void 0);
|
|
3156
|
+
}
|
|
3157
|
+
async function getGeneralLookupTableAccountsForPerena(perenaClient) {
|
|
3158
|
+
const bankMintInfo = mints.get("USD*");
|
|
3159
|
+
const juniorMintInfo = mints.get("USD*-J");
|
|
3160
|
+
const usdcMintInfo = mints.get("USDC");
|
|
3161
|
+
if (!bankMintInfo || !juniorMintInfo || !usdcMintInfo) {
|
|
3162
|
+
throw new Error("USD*, USD*-J, and USDC must exist in the mint registry");
|
|
3163
|
+
}
|
|
3164
|
+
const dummyUser = DEFAULT_PUBLIC_KEY;
|
|
3165
|
+
const bankMintUserAta = await getAtaAddress(
|
|
3166
|
+
bankMintInfo.address,
|
|
3167
|
+
dummyUser,
|
|
3168
|
+
bankMintInfo.tokenProgram
|
|
3169
|
+
);
|
|
3170
|
+
const juniorMintUserAta = await getAtaAddress(
|
|
3171
|
+
juniorMintInfo.address,
|
|
3172
|
+
dummyUser,
|
|
3173
|
+
juniorMintInfo.tokenProgram
|
|
3174
|
+
);
|
|
3175
|
+
const usdcMintUserAta = await getAtaAddress(
|
|
3176
|
+
usdcMintInfo.address,
|
|
3177
|
+
dummyUser,
|
|
3178
|
+
usdcMintInfo.tokenProgram
|
|
3179
|
+
);
|
|
3180
|
+
const allAccounts = [];
|
|
3181
|
+
const stakeQuote = await perenaClient.getQuote({
|
|
3182
|
+
inputMint: bankMintInfo.address,
|
|
3183
|
+
outputMint: juniorMintInfo.address,
|
|
3184
|
+
amount: wholeTokenAmount(bankMintInfo.decimals),
|
|
3185
|
+
slippageBps: 50
|
|
3186
|
+
});
|
|
3187
|
+
const stakeCpi = await perenaClient.getSwapCpiData(stakeQuote, dummyUser);
|
|
3188
|
+
allAccounts.push(
|
|
3189
|
+
...filterSpecificAccounts(
|
|
3190
|
+
stakeCpi.accounts.map((account) => account.address),
|
|
3191
|
+
[DEFAULT_PUBLIC_KEY, bankMintUserAta, juniorMintUserAta]
|
|
3192
|
+
)
|
|
3193
|
+
);
|
|
3194
|
+
const mintQuote = await perenaClient.getQuote({
|
|
3195
|
+
inputMint: usdcMintInfo.address,
|
|
3196
|
+
outputMint: bankMintInfo.address,
|
|
3197
|
+
amount: wholeTokenAmount(usdcMintInfo.decimals),
|
|
3198
|
+
slippageBps: 50
|
|
3199
|
+
});
|
|
3200
|
+
const mintCpi = await perenaClient.getSwapCpiData(mintQuote, dummyUser);
|
|
3201
|
+
allAccounts.push(
|
|
3202
|
+
...filterSpecificAccounts(
|
|
3203
|
+
mintCpi.accounts.map((account) => account.address),
|
|
3204
|
+
[DEFAULT_PUBLIC_KEY, usdcMintUserAta, bankMintUserAta]
|
|
3205
|
+
)
|
|
3206
|
+
);
|
|
3207
|
+
const burnQuote = await perenaClient.getQuote({
|
|
3208
|
+
inputMint: bankMintInfo.address,
|
|
3209
|
+
outputMint: usdcMintInfo.address,
|
|
3210
|
+
amount: wholeTokenAmount(bankMintInfo.decimals),
|
|
3211
|
+
slippageBps: 50
|
|
3212
|
+
});
|
|
3213
|
+
const burnCpi = await perenaClient.getSwapCpiData(burnQuote, dummyUser);
|
|
3214
|
+
allAccounts.push(
|
|
3215
|
+
...filterSpecificAccounts(
|
|
3216
|
+
burnCpi.accounts.map((account) => account.address),
|
|
3217
|
+
[DEFAULT_PUBLIC_KEY, bankMintUserAta, usdcMintUserAta]
|
|
3218
|
+
)
|
|
3219
|
+
);
|
|
3220
|
+
return dedupeOrderedAddresses(allAccounts);
|
|
3221
|
+
}
|
|
3222
|
+
|
|
3223
|
+
// ../../shared/oracle-service/src/oracle.ts
|
|
3224
|
+
import { address as address8 } from "@solana/kit";
|
|
3225
|
+
|
|
3226
|
+
// ../../shared/oracle-service/src/constants/switchboard.ts
|
|
3227
|
+
var SWITCHBOARD_PRICE_FEED_IDS = {
|
|
3228
|
+
SOL: {
|
|
3229
|
+
feedId: "4Hmd6PdjVA9auCoScE12iaBogfwS4ZXQ6VZoBeqanwWW",
|
|
3230
|
+
feedHash: "0x1f42dfb21efb24828b99fbe70e6d139cd665aafcbb1706bccd8f2a9b12562db6"
|
|
3231
|
+
}
|
|
3232
|
+
};
|
|
3233
|
+
|
|
3234
|
+
// ../../shared/oracle-service/src/feeds/jupiter.ts
|
|
3235
|
+
import { retry } from "ts-retry";
|
|
3236
|
+
|
|
3237
|
+
// ../../shared/oracle-service/src/feeds/priceBase.ts
|
|
3238
|
+
var PriceBase = class {
|
|
3239
|
+
constructor() {
|
|
3240
|
+
this.dataCache = new DataCache({
|
|
3241
|
+
defaultTtlMs: PRICE_STALENESS_SECONDS * 1e3
|
|
3242
|
+
});
|
|
3243
|
+
}
|
|
3244
|
+
async fetchPrices(mints2, bypassCache, context) {
|
|
3245
|
+
if (!mints2.length) {
|
|
3246
|
+
return {};
|
|
3247
|
+
}
|
|
3248
|
+
if (bypassCache) {
|
|
3249
|
+
return await this.internalFetchPrices(mints2, context);
|
|
3250
|
+
}
|
|
3251
|
+
const { data } = await this.dataCache.getDataBatch(
|
|
3252
|
+
async () => {
|
|
3253
|
+
const prices = await this.internalFetchPrices(mints2, context);
|
|
3254
|
+
return mints2.map((mint) => prices[mint] ?? null);
|
|
3255
|
+
},
|
|
3256
|
+
"prices",
|
|
3257
|
+
mints2
|
|
3258
|
+
);
|
|
3259
|
+
return Object.fromEntries(mints2.map((mint, i) => [mint, data[i] ?? 0]));
|
|
3260
|
+
}
|
|
3261
|
+
};
|
|
3262
|
+
|
|
3263
|
+
// ../../shared/oracle-service/src/feeds/jupiter.ts
|
|
3264
|
+
var JupiterPrices = class extends PriceBase {
|
|
3265
|
+
async getJupPriceData(mints2) {
|
|
3266
|
+
const batches = getBatches(mints2, 50);
|
|
3267
|
+
const results = await Promise.all(
|
|
3268
|
+
batches.map(
|
|
3269
|
+
(batch) => retry(
|
|
3270
|
+
async () => {
|
|
3271
|
+
const res = await (await fetch(
|
|
3272
|
+
"https://lite-api.jup.ag/price/v3?ids=" + batch.map((x) => x.toString()).join(",")
|
|
3273
|
+
)).json();
|
|
3274
|
+
if (!res || typeof res !== "object") {
|
|
3275
|
+
throw new Error("Failed to get mint prices using Jupiter");
|
|
3276
|
+
}
|
|
3277
|
+
return res;
|
|
3278
|
+
},
|
|
3279
|
+
{ maxTry: 6, delay: 250 }
|
|
3280
|
+
)
|
|
3281
|
+
)
|
|
3282
|
+
);
|
|
3283
|
+
return Object.assign({}, ...results);
|
|
3284
|
+
}
|
|
3285
|
+
async internalFetchPrices(mints2, _context) {
|
|
3286
|
+
if (mints2.length == 0) {
|
|
3287
|
+
return {};
|
|
3288
|
+
}
|
|
3289
|
+
const priceData = await this.getJupPriceData(mints2);
|
|
3290
|
+
const sortedPrices = {};
|
|
3291
|
+
for (const mint of mints2) {
|
|
3292
|
+
const key = mint.toString();
|
|
3293
|
+
if (priceData.hasOwnProperty(key)) {
|
|
3294
|
+
sortedPrices[key] = priceData[key];
|
|
3295
|
+
}
|
|
3296
|
+
}
|
|
3297
|
+
const prices = Object.fromEntries(
|
|
3298
|
+
mints2.map((mint) => [
|
|
3299
|
+
mint,
|
|
3300
|
+
sortedPrices !== null && typeof sortedPrices === "object" && typeof sortedPrices[mint.toString()] === "object" && "usdPrice" in sortedPrices[mint.toString()] ? { realtimePrice: parseFloat(sortedPrices[mint.toString()].usdPrice) } : { realtimePrice: 0 }
|
|
3301
|
+
])
|
|
3302
|
+
);
|
|
3303
|
+
return prices;
|
|
3304
|
+
}
|
|
3305
|
+
};
|
|
3306
|
+
|
|
3307
|
+
// ../../shared/oracle-service/src/constants/splStake.ts
|
|
3308
|
+
import { address as address7 } from "@solana/kit";
|
|
3309
|
+
var DFDVSOL_STAKE_POOL = address7("pyZMBjpWsVjKANAYK5mpNbKiws2krjRPZ2N2UYCSnbP");
|
|
3310
|
+
|
|
3311
|
+
// ../../shared/oracle-service/src/feeds/pyth.ts
|
|
3312
|
+
import { retry as retry2 } from "ts-retry";
|
|
3313
|
+
|
|
3314
|
+
// ../../shared/oracle-service/src/feeds/splStake.ts
|
|
3315
|
+
var SPL_STAKE_PRICE_CAP_MULTIPLIER = 1.1;
|
|
3316
|
+
var STAKE_POOL_TOTAL_LAMPORTS_OFFSET = 258;
|
|
3317
|
+
var STAKE_POOL_POOL_TOKEN_SUPPLY_OFFSET = 266;
|
|
3318
|
+
function errorWithCause(message, cause) {
|
|
3319
|
+
const err = new Error(message);
|
|
3320
|
+
err.cause = cause;
|
|
3321
|
+
return err;
|
|
3322
|
+
}
|
|
3323
|
+
function deriveValue(price, exponent) {
|
|
3324
|
+
if (exponent > 0) return Number(fromUiAmount(Number(price), exponent));
|
|
3325
|
+
if (exponent < 0) return toUiAmount(BigInt(price), Math.abs(exponent));
|
|
3326
|
+
return Number(price);
|
|
3327
|
+
}
|
|
3328
|
+
async function fetchStakeRate(rpcUrl, stakePool) {
|
|
3329
|
+
const rpc = createRpcWithRetry(rpcUrl);
|
|
3330
|
+
const redactedRpcUrl = redactRpcUrlForLog(rpcUrl);
|
|
3331
|
+
let response;
|
|
3332
|
+
try {
|
|
3333
|
+
response = await rpc.getAccountInfo(stakePool, { encoding: "base64" }).send();
|
|
3334
|
+
} catch (err) {
|
|
3335
|
+
throw errorWithCause(
|
|
3336
|
+
`SPL stake pool getAccountInfo failed (stakePool=${stakePool}, rpc=${redactedRpcUrl})`,
|
|
3337
|
+
err
|
|
3338
|
+
);
|
|
3339
|
+
}
|
|
3340
|
+
const { value } = response;
|
|
3341
|
+
if (!value) {
|
|
3342
|
+
throw new Error(
|
|
3343
|
+
`SPL stake pool account not found (stakePool=${stakePool}, rpc=${redactedRpcUrl})`
|
|
3344
|
+
);
|
|
3345
|
+
}
|
|
3346
|
+
const data = Buffer.from(value.data[0], "base64");
|
|
3347
|
+
const totalLamports = data.readBigUInt64LE(STAKE_POOL_TOTAL_LAMPORTS_OFFSET);
|
|
3348
|
+
const poolTokenSupply = data.readBigUInt64LE(STAKE_POOL_POOL_TOKEN_SUPPLY_OFFSET);
|
|
3349
|
+
if (poolTokenSupply === BigInt(0)) {
|
|
3350
|
+
throw new Error(
|
|
3351
|
+
`SPL stake pool has zero pool token supply (stakePool=${stakePool}, rpc=${redactedRpcUrl})`
|
|
3352
|
+
);
|
|
3353
|
+
}
|
|
3354
|
+
return Number(totalLamports) / Number(poolTokenSupply);
|
|
3355
|
+
}
|
|
3356
|
+
async function fetchSolUsd(feedId) {
|
|
3357
|
+
let resp;
|
|
3358
|
+
try {
|
|
3359
|
+
resp = await pythRequest([feedId]);
|
|
3360
|
+
} catch (err) {
|
|
3361
|
+
throw errorWithCause(`Pyth SOL/USD request failed before response (feedId=${feedId})`, err);
|
|
3362
|
+
}
|
|
3363
|
+
if (resp.status !== 200) {
|
|
3364
|
+
const body = await resp.text().catch(() => "<failed to read response body>");
|
|
3365
|
+
throw new Error(
|
|
3366
|
+
`Pyth SOL/USD request failed status=${resp.status} feedId=${feedId} body=${body}`
|
|
3367
|
+
);
|
|
3368
|
+
}
|
|
3369
|
+
let json;
|
|
3370
|
+
try {
|
|
3371
|
+
json = await resp.json();
|
|
3372
|
+
} catch (err) {
|
|
3373
|
+
throw errorWithCause(`Pyth SOL/USD response JSON parse failed (feedId=${feedId})`, err);
|
|
3374
|
+
}
|
|
3375
|
+
const price = json.parsed[0].price;
|
|
3376
|
+
return deriveValue(price.price, price.expo);
|
|
3377
|
+
}
|
|
3378
|
+
async function getSplStakeLstUiPrice(rpcUrl, config) {
|
|
3379
|
+
const [rate, solUsd] = await Promise.all([
|
|
3380
|
+
fetchStakeRate(rpcUrl, config.stakePool),
|
|
3381
|
+
fetchSolUsd(config.pythSolFeed.feedId)
|
|
3382
|
+
]);
|
|
3383
|
+
return Math.min(rate * solUsd, SPL_STAKE_PRICE_CAP_MULTIPLIER * solUsd);
|
|
3384
|
+
}
|
|
3385
|
+
|
|
3386
|
+
// ../../shared/oracle-service/src/utils/general.ts
|
|
3387
|
+
async function pythRequest(feedIds) {
|
|
3388
|
+
return await fetchWithRetry(
|
|
3389
|
+
`https://hermes.pyth.network/v2/updates/price/latest?${feedIds.map((x) => `ids%5B%5D=${x}`).join("&")}`
|
|
3390
|
+
);
|
|
3391
|
+
}
|
|
3392
|
+
var perenaOracleAccounts = new PerenaClient(getMainnetRpcUrl());
|
|
3393
|
+
function registerUsdStarOracle(oracle2) {
|
|
3394
|
+
oracle2.registerCustomOracle("USD*", {
|
|
3395
|
+
priceFetcher: (rpcUrl) => new PerenaClient(rpcUrl).getLatestBankMintUiPrice(),
|
|
3396
|
+
oracle: fromWeb3Pk(perenaOracleAccounts.sdkClient.bank),
|
|
3397
|
+
oracleType: 2 /* PerenaBank */
|
|
3398
|
+
});
|
|
3399
|
+
}
|
|
3400
|
+
function registerUsdStarJuniorOracle(oracle2) {
|
|
3401
|
+
oracle2.registerCustomOracle("USD*-J", {
|
|
3402
|
+
priceFetcher: (rpcUrl) => new PerenaClient(rpcUrl).getLatestJuniorMintUiPrice(),
|
|
3403
|
+
oracle: fromWeb3Pk(perenaOracleAccounts.sdkClient.tranche),
|
|
3404
|
+
oracleType: 3 /* PerenaTranche */
|
|
3405
|
+
});
|
|
3406
|
+
}
|
|
3407
|
+
function registerSplStakeLstOracle(oracle2, config) {
|
|
3408
|
+
oracle2.registerCustomOracle(config.mint, {
|
|
3409
|
+
priceFetcher: (rpcUrl) => getSplStakeLstUiPrice(rpcUrl, config),
|
|
3410
|
+
oracle: config.pythSolFeed.account,
|
|
3411
|
+
oracleType: 4 /* PythSplStake */,
|
|
3412
|
+
secondaryOracle: config.stakePool
|
|
3413
|
+
});
|
|
3414
|
+
}
|
|
3415
|
+
function registerDfdvSolOracle(oracle2) {
|
|
3416
|
+
const dfdvSol = mints.get("dfdvSOL");
|
|
3417
|
+
registerSplStakeLstOracle(oracle2, {
|
|
3418
|
+
mint: dfdvSol.address,
|
|
3419
|
+
stakePool: DFDVSOL_STAKE_POOL,
|
|
3420
|
+
pythSolFeed: PYTH_FEEDS.SOL
|
|
3421
|
+
});
|
|
3422
|
+
}
|
|
3423
|
+
|
|
3424
|
+
// ../../shared/oracle-service/src/feeds/pyth.ts
|
|
3425
|
+
var PythPrices = class extends PriceBase {
|
|
3426
|
+
constructor() {
|
|
3427
|
+
super(...arguments);
|
|
3428
|
+
this.deriveValue = (price, exponent) => {
|
|
3429
|
+
if (exponent > 0) {
|
|
3430
|
+
return Number(fromUiAmount(Number(price), exponent));
|
|
3431
|
+
} else if (exponent < 0) {
|
|
3432
|
+
return toUiAmount(BigInt(price), Math.abs(exponent));
|
|
3433
|
+
} else {
|
|
3434
|
+
return Number(price);
|
|
3435
|
+
}
|
|
3436
|
+
};
|
|
3437
|
+
}
|
|
3438
|
+
findFeed(symbol) {
|
|
3439
|
+
const key = findKeyIgnoreCase(PYTH_FEEDS, symbol);
|
|
3440
|
+
return key ? PYTH_FEEDS[key] : void 0;
|
|
3441
|
+
}
|
|
3442
|
+
async internalFetchPrices(mints2, _context) {
|
|
3443
|
+
const feedIds = mints2.map((mint) => {
|
|
3444
|
+
const symbol = mints.get(mint)?.symbol;
|
|
3445
|
+
const feed = symbol ? this.findFeed(symbol) : void 0;
|
|
3446
|
+
if (!feed) {
|
|
3447
|
+
throw new Error(`No Pyth feed configured for mint ${mint.toString()}`);
|
|
3448
|
+
}
|
|
3449
|
+
return feed.feedId;
|
|
3450
|
+
});
|
|
3451
|
+
const prices = await retry2(
|
|
3452
|
+
async () => {
|
|
3453
|
+
const resp = await pythRequest(feedIds);
|
|
3454
|
+
const status = resp.status;
|
|
3455
|
+
if (status !== 200) {
|
|
3456
|
+
const body = await resp.text().catch(() => "<failed to read response body>");
|
|
3457
|
+
throw new Error(
|
|
3458
|
+
`Pyth price request failed status=${status} statusText=${resp.statusText} feedIds=${feedIds.join(",")} body=${body}`
|
|
3459
|
+
);
|
|
3460
|
+
}
|
|
3461
|
+
const json = await resp.json();
|
|
3462
|
+
const prices2 = json.parsed.map((x) => {
|
|
3463
|
+
return {
|
|
3464
|
+
realtimePrice: this.deriveValue(x.price.price, x.price.expo),
|
|
3465
|
+
emaPrice: this.deriveValue(x.ema_price.price, x.ema_price.expo)
|
|
3466
|
+
};
|
|
3467
|
+
});
|
|
3468
|
+
return prices2;
|
|
3469
|
+
},
|
|
3470
|
+
{
|
|
3471
|
+
maxTry: 5,
|
|
3472
|
+
delay: 250
|
|
3473
|
+
}
|
|
3474
|
+
);
|
|
3475
|
+
return createRecord(
|
|
3476
|
+
mints2.map((x) => x.toString()),
|
|
3477
|
+
prices
|
|
3478
|
+
);
|
|
3479
|
+
}
|
|
3480
|
+
};
|
|
3481
|
+
|
|
3482
|
+
// ../../shared/oracle-service/src/feeds/switchboard.ts
|
|
3483
|
+
var SwitchboardPrices = class extends PriceBase {
|
|
3484
|
+
async internalFetchPrices(mints2, _context) {
|
|
3485
|
+
return {};
|
|
3486
|
+
}
|
|
3487
|
+
};
|
|
3488
|
+
|
|
3489
|
+
// ../../shared/oracle-service/src/feeds/custom.ts
|
|
3490
|
+
var CustomPrices = class extends PriceBase {
|
|
3491
|
+
constructor() {
|
|
3492
|
+
super(...arguments);
|
|
3493
|
+
this.customOracles = /* @__PURE__ */ new Map();
|
|
3494
|
+
}
|
|
3495
|
+
getLookupKeys(mint) {
|
|
3496
|
+
const symbol = mints.get(mint)?.symbol;
|
|
3497
|
+
const address9 = mints.get(mint)?.address;
|
|
3498
|
+
return [mint, symbol, address9].filter((key) => key !== void 0);
|
|
3499
|
+
}
|
|
3500
|
+
/**
|
|
3501
|
+
* Register a custom price fetcher for a given mint.
|
|
3502
|
+
*
|
|
3503
|
+
* @param mint - The mint identifier
|
|
3504
|
+
* @param fetcher - An async function that returns the current price
|
|
3505
|
+
*/
|
|
3506
|
+
registerCustomOracle(mint, oracle2) {
|
|
3507
|
+
this.customOracles.set(mint, oracle2);
|
|
3508
|
+
}
|
|
3509
|
+
/**
|
|
3510
|
+
* Check if a custom price fetcher is registered for a given mint.
|
|
3511
|
+
*/
|
|
3512
|
+
hasCustomOracle(mint) {
|
|
3513
|
+
return this.getLookupKeys(mint).some((key) => this.customOracles.has(key));
|
|
3514
|
+
}
|
|
3515
|
+
async internalFetchPrices(mints2, context) {
|
|
3516
|
+
const rpcUrl = context?.rpcUrl;
|
|
3517
|
+
if (!rpcUrl) {
|
|
3518
|
+
throw new Error("Custom oracle price fetch requires an RPC URL");
|
|
3519
|
+
}
|
|
3520
|
+
const entries = await Promise.all(
|
|
3521
|
+
mints2.map(async (mint) => {
|
|
3522
|
+
const oracle2 = this.getCustomOracle(mint);
|
|
3523
|
+
if (!oracle2) {
|
|
3524
|
+
return [mint, { realtimePrice: 0 }];
|
|
3525
|
+
}
|
|
3526
|
+
const price = await oracle2.priceFetcher(rpcUrl);
|
|
3527
|
+
return [mint, { realtimePrice: price }];
|
|
3528
|
+
})
|
|
3529
|
+
);
|
|
3530
|
+
return Object.fromEntries(entries);
|
|
3531
|
+
}
|
|
3532
|
+
getCustomOracle(mint) {
|
|
3533
|
+
for (const key of this.getLookupKeys(mint)) {
|
|
3534
|
+
const oracle2 = this.customOracles.get(key);
|
|
3535
|
+
if (oracle2) {
|
|
3536
|
+
return oracle2;
|
|
3537
|
+
}
|
|
3538
|
+
}
|
|
3539
|
+
return void 0;
|
|
3540
|
+
}
|
|
3541
|
+
};
|
|
3542
|
+
|
|
3543
|
+
// ../../shared/oracle-service/src/oracle.ts
|
|
3544
|
+
var OracleService = class {
|
|
3545
|
+
constructor() {
|
|
3546
|
+
this.jupiter = new JupiterPrices();
|
|
3547
|
+
this.pyth = new PythPrices();
|
|
3548
|
+
this.switchboard = new SwitchboardPrices();
|
|
3549
|
+
this.custom = new CustomPrices();
|
|
3550
|
+
}
|
|
3551
|
+
/**
|
|
3552
|
+
* Register a custom oracle for a given mint.
|
|
3553
|
+
* Custom-registered mints take priority over all other oracle sources.
|
|
3554
|
+
*/
|
|
3555
|
+
registerCustomOracle(mint, oracle2) {
|
|
3556
|
+
this.custom.registerCustomOracle(mint, oracle2);
|
|
3557
|
+
}
|
|
3558
|
+
getOracleData(mint) {
|
|
3559
|
+
const customOracle = this.custom.getCustomOracle(mint);
|
|
3560
|
+
if (customOracle) {
|
|
3561
|
+
return {
|
|
3562
|
+
oracle: customOracle.oracle,
|
|
3563
|
+
oracleType: customOracle.oracleType,
|
|
3564
|
+
secondaryOracle: customOracle.secondaryOracle
|
|
3565
|
+
};
|
|
3566
|
+
}
|
|
3567
|
+
const symbol = mints.get(mint)?.symbol;
|
|
3568
|
+
const pythSymbol = symbol ? findKeyIgnoreCase(PYTH_FEEDS, symbol) : void 0;
|
|
3569
|
+
const switchboardSymbol = symbol ? findKeyIgnoreCase(SWITCHBOARD_PRICE_FEED_IDS, symbol) : void 0;
|
|
3570
|
+
return {
|
|
3571
|
+
oracle: pythSymbol ? PYTH_FEEDS[pythSymbol].account : address8(SWITCHBOARD_PRICE_FEED_IDS[switchboardSymbol].feedId),
|
|
3572
|
+
oracleType: pythSymbol ? 0 /* Pyth */ : 1 /* Switchboard */,
|
|
3573
|
+
secondaryOracle: void 0
|
|
3574
|
+
};
|
|
3575
|
+
}
|
|
3576
|
+
clearCache() {
|
|
3577
|
+
this.jupiter.dataCache.clearAllCache();
|
|
3578
|
+
this.pyth.dataCache.clearAllCache();
|
|
3579
|
+
this.switchboard.dataCache.clearAllCache();
|
|
3580
|
+
this.custom.dataCache.clearAllCache();
|
|
3581
|
+
}
|
|
3582
|
+
async fetchPrices(mints2, mode, bypassCache, environment = ENVIRONMENT) {
|
|
3583
|
+
if (!mints2.length) {
|
|
3584
|
+
return {};
|
|
3585
|
+
}
|
|
3586
|
+
const rpcUrl = getRpcUrl(environment);
|
|
3587
|
+
const customMints = [];
|
|
3588
|
+
const pythMints = [];
|
|
3589
|
+
const switchboardMints = [];
|
|
3590
|
+
const jupiterMints = [];
|
|
3591
|
+
for (const mint of mints2) {
|
|
3592
|
+
if (this.custom.hasCustomOracle(mint)) {
|
|
3593
|
+
customMints.push(mint);
|
|
3594
|
+
} else {
|
|
3595
|
+
const symbol = mints.get(mint)?.symbol;
|
|
3596
|
+
if (symbol && findKeyIgnoreCase(PYTH_FEEDS, symbol)) {
|
|
3597
|
+
pythMints.push(mint);
|
|
3598
|
+
} else if (symbol && findKeyIgnoreCase(SWITCHBOARD_PRICE_FEED_IDS, symbol)) {
|
|
3599
|
+
switchboardMints.push(mint);
|
|
3600
|
+
} else {
|
|
3601
|
+
jupiterMints.push(mint);
|
|
3602
|
+
}
|
|
3603
|
+
}
|
|
3604
|
+
}
|
|
3605
|
+
const [customPrices, pythPrices, switchboardPrices, jupiterPrices] = await Promise.all([
|
|
3606
|
+
customMints.length ? this.custom.fetchPrices(customMints, bypassCache, { rpcUrl }) : {},
|
|
3607
|
+
pythMints.length ? this.pyth.fetchPrices(pythMints, bypassCache) : {},
|
|
3608
|
+
switchboardMints.length ? this.switchboard.fetchPrices(switchboardMints, bypassCache) : {},
|
|
3609
|
+
jupiterMints.length ? this.jupiter.fetchPrices(jupiterMints, bypassCache) : {}
|
|
3610
|
+
]);
|
|
3611
|
+
const toNumber = (result) => mode === "realtime" ? result.realtimePrice : result.emaPrice ?? result.realtimePrice;
|
|
3612
|
+
const prices = {};
|
|
3613
|
+
for (const mint of mints2) {
|
|
3614
|
+
const price = toNumber(
|
|
3615
|
+
customPrices[mint] ?? pythPrices[mint] ?? switchboardPrices[mint] ?? jupiterPrices[mint]
|
|
3616
|
+
);
|
|
3617
|
+
const isStablecoin = mints.get(mint)?.assetType === "Stablecoin";
|
|
3618
|
+
prices[mint] = isStablecoin ? Math.min(price, 1) : price;
|
|
3619
|
+
}
|
|
3620
|
+
return prices;
|
|
3621
|
+
}
|
|
3622
|
+
};
|
|
3623
|
+
var oracle = new OracleService();
|
|
3624
|
+
registerUsdStarOracle(oracle);
|
|
3625
|
+
registerUsdStarJuniorOracle(oracle);
|
|
3626
|
+
registerDfdvSolOracle(oracle);
|
|
3627
|
+
|
|
3628
|
+
export {
|
|
3629
|
+
toCustomAccountMeta,
|
|
3630
|
+
accountExists,
|
|
3631
|
+
toWeb3Pk,
|
|
3632
|
+
fromWeb3Pk,
|
|
3633
|
+
toWeb3AccountMeta,
|
|
3634
|
+
toKitInstruction,
|
|
3635
|
+
getAtaAddress,
|
|
3636
|
+
fetchSplTokenAccountAmounts,
|
|
3637
|
+
DataCache,
|
|
3638
|
+
BaseAccountClient,
|
|
3639
|
+
applyDataCacheTransactionInvalidations,
|
|
3640
|
+
createMultiCpiRefs,
|
|
3641
|
+
createCpiRefs,
|
|
3642
|
+
dedupeOrderedAddresses,
|
|
3643
|
+
maxByNumber,
|
|
3644
|
+
sleep,
|
|
3645
|
+
createSignerFromAddress,
|
|
3646
|
+
getSlot,
|
|
3647
|
+
ENVIRONMENT,
|
|
3648
|
+
DAYS_PER_YEAR,
|
|
3649
|
+
TVL_USD_DECIMAL_PLACES,
|
|
3650
|
+
DEFAULT_PUBLIC_KEY,
|
|
3651
|
+
LOCALNET_URL,
|
|
3652
|
+
PROTOCOL_ADMIN,
|
|
3653
|
+
DEPLOYED_ADMIN_KEYPAIR_FP,
|
|
3654
|
+
PRICE_STALENESS_SECONDS,
|
|
3655
|
+
U64_MAX_BN,
|
|
3656
|
+
toUiAmount,
|
|
3657
|
+
fromUiAmount,
|
|
3658
|
+
calculateTvlUsd,
|
|
3659
|
+
tvlUsdToBaseUnits,
|
|
3660
|
+
bnFromBigInt,
|
|
3661
|
+
applyFeeCeil,
|
|
3662
|
+
currentUnixSeconds,
|
|
3663
|
+
sum,
|
|
3664
|
+
toBigInt,
|
|
3665
|
+
applyBps,
|
|
3666
|
+
toSafeNumber,
|
|
3667
|
+
numToU64Bytes,
|
|
3668
|
+
mints,
|
|
3669
|
+
mintSymbol,
|
|
3670
|
+
requestHeapFrameIx,
|
|
3671
|
+
getCreateAtaInstructions,
|
|
3672
|
+
getCreateAtaIxIfNeeded,
|
|
3673
|
+
getWrapSolInstructions,
|
|
3674
|
+
getUnwrapSolInstruction,
|
|
3675
|
+
fetchWithRetry,
|
|
3676
|
+
createRpcWithRetry,
|
|
3677
|
+
createRpcWithFailover,
|
|
3678
|
+
createRpc,
|
|
3679
|
+
getRpcUrl,
|
|
3680
|
+
getRpcUrls,
|
|
3681
|
+
createReadOnlyAnchorProvider,
|
|
3682
|
+
RENT_SYSVAR_META,
|
|
3683
|
+
SYSTEM_PROGRAM_META,
|
|
3684
|
+
IX_SYSVAR_META,
|
|
3685
|
+
CpiTypes,
|
|
3686
|
+
lutManager,
|
|
3687
|
+
JITO_TIP_ACCOUNTS,
|
|
3688
|
+
TransactionError,
|
|
3689
|
+
signSendAndConfirmTransaction,
|
|
3690
|
+
enumToOracleType,
|
|
3691
|
+
ExternalLiquidityTypeToEnum,
|
|
3692
|
+
enumToExternalLiquidityType,
|
|
3693
|
+
enumToTokenProgram,
|
|
3694
|
+
lendingPlatformToEnum,
|
|
3695
|
+
enumToLendingPlatform,
|
|
3696
|
+
resolveTokenProgram,
|
|
3697
|
+
createMint,
|
|
3698
|
+
BaseIXBuilderService,
|
|
3699
|
+
swapClientCanRoute,
|
|
3700
|
+
PYTH_FEEDS,
|
|
3701
|
+
PERENA_PROGRAM_ID,
|
|
3702
|
+
PerenaClient,
|
|
3703
|
+
getPerenaWithdrawalQueueAddressesFromCpiData,
|
|
3704
|
+
getGeneralLookupTableAccountsForPerena,
|
|
3705
|
+
oracle
|
|
3706
|
+
};
|
|
3707
|
+
//# sourceMappingURL=chunk-2T23QQCX.mjs.map
|