@upshiftfinance/sdk 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +408 -2
- package/lib/abis/AddressResolver.d.ts +28 -0
- package/lib/abis/AddressResolver.js +23 -0
- package/lib/abis/ChainlinkV3.d.ts +87 -0
- package/lib/abis/ChainlinkV3.js +117 -0
- package/lib/abis/ERC20.d.ts +168 -0
- package/lib/abis/ERC20.js +226 -0
- package/lib/abis/ERC20_Bytes32.d.ts +139 -0
- package/lib/abis/ERC20_Bytes32.js +196 -0
- package/lib/abis/ERC4626.d.ts +364 -0
- package/lib/abis/ERC4626.js +507 -0
- package/lib/abis/ERC721.d.ts +231 -0
- package/lib/abis/ERC721.js +321 -0
- package/lib/abis/FeeOracle.d.ts +120 -0
- package/lib/abis/FeeOracle.js +162 -0
- package/lib/abis/LendingPool.d.ts +1393 -0
- package/lib/abis/LendingPool.js +1807 -0
- package/lib/abis/LendingPoolV2.d.ts +1413 -0
- package/lib/abis/LendingPoolV2.js +1833 -0
- package/lib/abis/LendingPoolV3.d.ts +1677 -0
- package/lib/abis/LendingPoolV3.js +1160 -0
- package/lib/abis/Loan.d.ts +837 -0
- package/lib/abis/Loan.js +1080 -0
- package/lib/abis/MultiAssetNativeDepositWrapper.d.ts +137 -0
- package/lib/abis/MultiAssetNativeDepositWrapper.js +125 -0
- package/lib/abis/Multicall3.d.ts +30 -0
- package/lib/abis/Multicall3.js +97 -0
- package/lib/abis/OFT.d.ts +116 -0
- package/lib/abis/OFT.js +85 -0
- package/lib/abis/PoolAdapter.d.ts +36 -0
- package/lib/abis/PoolAdapter.js +51 -0
- package/lib/abis/RewardDistributor.d.ts +267 -0
- package/lib/abis/RewardDistributor.js +352 -0
- package/lib/abis/RwaRedeemSubaccount.d.ts +747 -0
- package/lib/abis/RwaRedeemSubaccount.js +548 -0
- package/lib/abis/SmartAccount.d.ts +17 -0
- package/lib/abis/SmartAccount.js +19 -0
- package/lib/abis/SwapRouter.d.ts +953 -0
- package/lib/abis/SwapRouter.js +1228 -0
- package/lib/abis/TextResolver.d.ts +16 -0
- package/lib/abis/TextResolver.js +16 -0
- package/lib/abis/TokenizedVaultV2.d.ts +1364 -0
- package/lib/abis/TokenizedVaultV2.js +1041 -0
- package/lib/abis/TokenizedVaultV2DepositWithPermit.d.ts +1456 -0
- package/lib/abis/TokenizedVaultV2DepositWithPermit.js +1878 -0
- package/lib/abis/TokenizedVaultV2Receipt.d.ts +1568 -0
- package/lib/abis/TokenizedVaultV2Receipt.js +1061 -0
- package/lib/abis/TokenizedVaultV2SenderAllocationWhitelist.d.ts +454 -0
- package/lib/abis/TokenizedVaultV2SenderAllocationWhitelist.js +327 -0
- package/lib/abis/TokenizedVaultV2WhitelistedAllocation.d.ts +1466 -0
- package/lib/abis/TokenizedVaultV2WhitelistedAllocation.js +1092 -0
- package/lib/abis/TokenizedVaultV2WhitelistedAssets.d.ts +274 -0
- package/lib/abis/TokenizedVaultV2WhitelistedAssets.js +167 -0
- package/lib/abis/UniversalResolverResolve.d.ts +69 -0
- package/lib/abis/UniversalResolverResolve.js +35 -0
- package/lib/abis/UniversalSignatureValidator.d.ts +17 -0
- package/lib/abis/UniversalSignatureValidator.js +30 -0
- package/lib/abis/WrapperAdapter.d.ts +71 -0
- package/lib/abis/WrapperAdapter.js +77 -0
- package/lib/abis/index.d.ts +34 -0
- package/lib/abis/index.js +51 -0
- package/lib/adapters/evm/getters.d.ts +19 -0
- package/lib/adapters/evm/getters.js +249 -0
- package/lib/adapters/evm/index.d.ts +539 -0
- package/lib/adapters/evm/index.js +656 -0
- package/lib/adapters/evm/utils.d.ts +8 -0
- package/lib/adapters/evm/utils.js +51 -0
- package/lib/adapters/solana/confirm.d.ts +88 -0
- package/lib/adapters/solana/confirm.js +291 -0
- package/lib/adapters/solana/constants.d.ts +42 -0
- package/lib/adapters/solana/constants.js +59 -0
- package/lib/adapters/solana/getters.d.ts +42 -0
- package/lib/adapters/solana/getters.js +275 -0
- package/lib/adapters/solana/idl/vault-idl.d.ts +700 -0
- package/lib/adapters/solana/idl/vault-idl.js +2101 -0
- package/lib/adapters/solana/idl/withdrawal-queue-idl.d.ts +795 -0
- package/lib/adapters/solana/idl/withdrawal-queue-idl.js +1864 -0
- package/lib/adapters/solana/index.d.ts +372 -0
- package/lib/adapters/solana/index.js +459 -0
- package/lib/adapters/solana/pricing.d.ts +184 -0
- package/lib/adapters/solana/pricing.js +239 -0
- package/lib/adapters/solana/queue-hints.d.ts +29 -0
- package/lib/adapters/solana/queue-hints.js +59 -0
- package/lib/adapters/solana/queue.actions.d.ts +97 -0
- package/lib/adapters/solana/queue.actions.js +468 -0
- package/lib/adapters/solana/token-reads.d.ts +108 -0
- package/lib/adapters/solana/token-reads.js +145 -0
- package/lib/adapters/solana/types.d.ts +325 -0
- package/lib/adapters/solana/types.js +3 -0
- package/lib/adapters/solana/utils.d.ts +229 -0
- package/lib/adapters/solana/utils.js +773 -0
- package/lib/adapters/solana/vault.actions.d.ts +140 -0
- package/lib/adapters/solana/vault.actions.js +657 -0
- package/lib/adapters/solana/withdrawal-queue.d.ts +125 -0
- package/lib/adapters/solana/withdrawal-queue.js +301 -0
- package/lib/adapters/stellar/actions.d.ts +41 -0
- package/lib/adapters/stellar/actions.js +126 -0
- package/lib/adapters/stellar/constants.d.ts +43 -0
- package/lib/adapters/stellar/constants.js +53 -0
- package/lib/adapters/stellar/getters.d.ts +68 -0
- package/lib/adapters/stellar/getters.js +290 -0
- package/lib/adapters/stellar/index.d.ts +126 -0
- package/lib/adapters/stellar/index.js +187 -0
- package/lib/adapters/stellar/invocation.d.ts +55 -0
- package/lib/adapters/stellar/invocation.js +92 -0
- package/lib/adapters/stellar/soroban.d.ts +131 -0
- package/lib/adapters/stellar/soroban.js +617 -0
- package/lib/adapters/stellar/submit.d.ts +42 -0
- package/lib/adapters/stellar/submit.js +195 -0
- package/lib/adapters/stellar/types.d.ts +57 -0
- package/lib/adapters/stellar/types.js +6 -0
- package/lib/adapters/stellar/utils.d.ts +24 -0
- package/lib/adapters/stellar/utils.js +34 -0
- package/lib/adapters/sui/constants.d.ts +1 -0
- package/lib/adapters/sui/constants.js +9 -0
- package/lib/adapters/sui/getters.d.ts +24 -0
- package/lib/adapters/sui/getters.js +134 -0
- package/lib/adapters/sui/index.d.ts +53 -0
- package/lib/adapters/sui/index.js +96 -0
- package/lib/adapters/sui/transformer.d.ts +10 -0
- package/lib/adapters/sui/transformer.js +115 -0
- package/lib/adapters/sui/types.d.ts +70 -0
- package/lib/adapters/sui/types.js +3 -0
- package/lib/adapters/sui/utils.d.ts +8 -0
- package/lib/adapters/sui/utils.js +17 -0
- package/lib/core/analytics/app-name.d.ts +27 -0
- package/lib/core/analytics/app-name.js +48 -0
- package/lib/core/analytics/chain-name.d.ts +9 -0
- package/lib/core/analytics/chain-name.js +34 -0
- package/lib/core/analytics/constants.d.ts +15 -0
- package/lib/core/analytics/constants.js +28 -0
- package/lib/core/analytics/env.d.ts +46 -0
- package/lib/core/analytics/env.js +147 -0
- package/lib/core/analytics/index.d.ts +39 -0
- package/lib/core/analytics/index.js +83 -0
- package/lib/core/analytics/instrumentation.d.ts +29 -0
- package/lib/core/analytics/instrumentation.js +292 -0
- package/lib/core/analytics/method-taxonomy.d.ts +19 -0
- package/lib/core/analytics/method-taxonomy.js +156 -0
- package/lib/core/analytics/metrics.d.ts +48 -0
- package/lib/core/analytics/metrics.js +142 -0
- package/lib/core/analytics/sanitize.d.ts +57 -0
- package/lib/core/analytics/sanitize.js +272 -0
- package/lib/core/analytics/sentry-runtime.d.ts +15 -0
- package/lib/core/analytics/sentry-runtime.js +131 -0
- package/lib/core/analytics/sentry.d.ts +100 -0
- package/lib/core/analytics/sentry.js +696 -0
- package/lib/core/analytics/types.d.ts +55 -0
- package/lib/core/analytics/types.js +3 -0
- package/lib/core/analytics/user-identity.d.ts +55 -0
- package/lib/core/analytics/user-identity.js +218 -0
- package/lib/core/analytics/version.d.ts +6 -0
- package/lib/core/analytics/version.js +10 -0
- package/lib/core/attribution.d.ts +159 -0
- package/lib/core/attribution.js +194 -0
- package/lib/core/auth/index.d.ts +1 -0
- package/lib/core/auth/index.js +18 -0
- package/lib/core/auth/verify.d.ts +2 -0
- package/lib/core/auth/verify.js +35 -0
- package/lib/core/base.class.d.ts +193 -0
- package/lib/core/base.class.js +163 -0
- package/lib/core/cache.d.ts +9 -0
- package/lib/core/cache.js +31 -0
- package/lib/core/constants/adapters.d.ts +103 -0
- package/lib/core/constants/adapters.js +180 -0
- package/lib/core/constants/core.d.ts +162 -0
- package/lib/core/constants/core.js +281 -0
- package/lib/core/constants/swap-router.d.ts +180 -0
- package/lib/core/constants/swap-router.js +203 -0
- package/lib/core/constants/vaults.d.ts +93 -0
- package/lib/core/constants/vaults.js +277 -0
- package/lib/core/constants/web3.d.ts +106 -0
- package/lib/core/constants/web3.js +251 -0
- package/lib/core/errors/index.d.ts +177 -0
- package/lib/core/errors/index.js +257 -0
- package/lib/core/fetcher.d.ts +237 -0
- package/lib/core/fetcher.js +1103 -0
- package/lib/core/helpers/adapters.d.ts +13 -0
- package/lib/core/helpers/adapters.js +39 -0
- package/lib/core/helpers/chain-address.d.ts +13 -0
- package/lib/core/helpers/chain-address.js +47 -0
- package/lib/core/helpers/chain-error.d.ts +207 -0
- package/lib/core/helpers/chain-error.js +697 -0
- package/lib/core/helpers/chain-support.d.ts +98 -0
- package/lib/core/helpers/chain-support.js +139 -0
- package/lib/core/helpers/concurrency.d.ts +51 -0
- package/lib/core/helpers/concurrency.js +79 -0
- package/lib/core/helpers/core.d.ts +92 -0
- package/lib/core/helpers/core.js +368 -0
- package/lib/core/helpers/explorer-link.d.ts +16 -0
- package/lib/core/helpers/explorer-link.js +26 -0
- package/lib/core/helpers/multicall.d.ts +68 -0
- package/lib/core/helpers/multicall.js +103 -0
- package/lib/core/helpers/revert-decode.d.ts +248 -0
- package/lib/core/helpers/revert-decode.js +515 -0
- package/lib/core/helpers/signer.d.ts +61 -0
- package/lib/core/helpers/signer.js +184 -0
- package/lib/core/helpers/swap-router.d.ts +269 -0
- package/lib/core/helpers/swap-router.js +542 -0
- package/lib/core/helpers/vault-version.d.ts +24 -0
- package/lib/core/helpers/vault-version.js +83 -0
- package/lib/core/helpers/vaults.d.ts +89 -0
- package/lib/core/helpers/vaults.js +241 -0
- package/lib/core/helpers/web3.d.ts +366 -0
- package/lib/core/helpers/web3.js +1034 -0
- package/lib/core/index.d.ts +23 -0
- package/lib/core/index.js +40 -0
- package/lib/core/logger/curator-alert.d.ts +217 -0
- package/lib/core/logger/curator-alert.js +276 -0
- package/lib/core/logger/index.d.ts +99 -0
- package/lib/core/logger/index.js +163 -0
- package/lib/core/logger/slack.d.ts +49 -0
- package/lib/core/logger/slack.js +111 -0
- package/lib/core/vault-metadata.d.ts +12 -0
- package/lib/core/vault-metadata.js +42 -0
- package/lib/core/version-check.d.ts +58 -0
- package/lib/core/version-check.js +182 -0
- package/lib/evm/index.d.ts +2 -0
- package/lib/evm/index.js +19 -0
- package/lib/evm/methods/crossChainVault.d.ts +132 -0
- package/lib/evm/methods/crossChainVault.js +857 -0
- package/lib/evm/methods/crossChainVaultRegistry.d.ts +92 -0
- package/lib/evm/methods/crossChainVaultRegistry.js +239 -0
- package/lib/evm/methods/index.d.ts +2 -0
- package/lib/evm/methods/index.js +19 -0
- package/lib/evm/types/crossChain.d.ts +363 -0
- package/lib/evm/types/crossChain.js +20 -0
- package/lib/evm/types/index.d.ts +1 -0
- package/lib/evm/types/index.js +18 -0
- package/lib/index.d.ts +30 -0
- package/lib/index.js +52 -0
- package/lib/main.d.ts +596 -0
- package/lib/main.js +681 -0
- package/lib/modules/api/fetcher.d.ts +108 -0
- package/lib/modules/api/fetcher.js +187 -0
- package/lib/modules/api/index.d.ts +1 -0
- package/lib/modules/api/index.js +6 -0
- package/lib/modules/api/main.d.ts +587 -0
- package/lib/modules/api/main.js +911 -0
- package/lib/modules/sub-accounts/fetcher.d.ts +53 -0
- package/lib/modules/sub-accounts/fetcher.js +96 -0
- package/lib/modules/sub-accounts/index.d.ts +2 -0
- package/lib/modules/sub-accounts/index.js +19 -0
- package/lib/modules/sub-accounts/main.d.ts +249 -0
- package/lib/modules/sub-accounts/main.js +211 -0
- package/lib/modules/sub-accounts/utils.d.ts +106 -0
- package/lib/modules/sub-accounts/utils.js +112 -0
- package/lib/modules/vaults/adapter.helpers.d.ts +84 -0
- package/lib/modules/vaults/adapter.helpers.js +202 -0
- package/lib/modules/vaults/fetcher.d.ts +147 -0
- package/lib/modules/vaults/fetcher.js +357 -0
- package/lib/modules/vaults/getters.d.ts +1060 -0
- package/lib/modules/vaults/getters.js +4079 -0
- package/lib/modules/vaults/index.d.ts +20 -0
- package/lib/modules/vaults/index.js +44 -0
- package/lib/modules/vaults/main.d.ts +607 -0
- package/lib/modules/vaults/main.js +1687 -0
- package/lib/modules/vaults/prefetch.d.ts +65 -0
- package/lib/modules/vaults/prefetch.js +120 -0
- package/lib/modules/vaults/read.actions.d.ts +406 -0
- package/lib/modules/vaults/read.actions.js +891 -0
- package/lib/modules/vaults/types.d.ts +149 -0
- package/lib/modules/vaults/types.js +3 -0
- package/lib/modules/vaults/utils/call-data-decoder.d.ts +61 -0
- package/lib/modules/vaults/utils/call-data-decoder.js +194 -0
- package/lib/modules/vaults/utils/date-utils.d.ts +50 -0
- package/lib/modules/vaults/utils/date-utils.js +84 -0
- package/lib/modules/vaults/utils.d.ts +153 -0
- package/lib/modules/vaults/utils.js +818 -0
- package/lib/modules/vaults/write.actions.d.ts +812 -0
- package/lib/modules/vaults/write.actions.js +2377 -0
- package/lib/polyfills.d.ts +1 -0
- package/lib/polyfills.js +12 -0
- package/lib/sdk.d.ts +30154 -0
- package/lib/services/coingecko/fetcher.d.ts +15 -0
- package/lib/services/coingecko/fetcher.js +67 -0
- package/lib/services/coingecko/index.d.ts +2 -0
- package/lib/services/coingecko/index.js +19 -0
- package/lib/services/coingecko/utils.d.ts +1 -0
- package/lib/services/coingecko/utils.js +24 -0
- package/lib/services/debank/fetcher.d.ts +126 -0
- package/lib/services/debank/fetcher.js +47 -0
- package/lib/services/debank/index.d.ts +2 -0
- package/lib/services/debank/index.js +19 -0
- package/lib/services/debank/utils.d.ts +50 -0
- package/lib/services/debank/utils.js +325 -0
- package/lib/services/layerzero/deposits.d.ts +55 -0
- package/lib/services/layerzero/deposits.js +174 -0
- package/lib/services/layerzero/redeems.d.ts +20 -0
- package/lib/services/layerzero/redeems.js +92 -0
- package/lib/services/layerzero/utils.d.ts +9 -0
- package/lib/services/layerzero/utils.js +22 -0
- package/lib/services/octavfi/fetcher.d.ts +33 -0
- package/lib/services/octavfi/fetcher.js +39 -0
- package/lib/services/octavfi/index.d.ts +3 -0
- package/lib/services/octavfi/index.js +20 -0
- package/lib/services/octavfi/types.d.ts +34 -0
- package/lib/services/octavfi/types.js +3 -0
- package/lib/services/octavfi/utils.d.ts +16 -0
- package/lib/services/octavfi/utils.js +244 -0
- package/lib/services/subgraph/fetcher.d.ts +2 -0
- package/lib/services/subgraph/fetcher.js +66 -0
- package/lib/services/subgraph/index.d.ts +2 -0
- package/lib/services/subgraph/index.js +19 -0
- package/lib/services/subgraph/schema.d.ts +48 -0
- package/lib/services/subgraph/schema.js +87 -0
- package/lib/services/subgraph/vaults.d.ts +83 -0
- package/lib/services/subgraph/vaults.js +1282 -0
- package/lib/services/swap-quotes/index.d.ts +105 -0
- package/lib/services/swap-quotes/index.js +77 -0
- package/lib/services/swap-quotes/paraswap.d.ts +51 -0
- package/lib/services/swap-quotes/paraswap.js +138 -0
- package/lib/services/untangled/fetcher.d.ts +40 -0
- package/lib/services/untangled/fetcher.js +110 -0
- package/lib/services/untangled/index.d.ts +3 -0
- package/lib/services/untangled/index.js +20 -0
- package/lib/services/untangled/types.d.ts +83 -0
- package/lib/services/untangled/types.js +10 -0
- package/lib/services/untangled/utils.d.ts +91 -0
- package/lib/services/untangled/utils.js +339 -0
- package/lib/types/api.d.ts +498 -0
- package/lib/types/api.js +3 -0
- package/lib/types/index.d.ts +12 -0
- package/lib/types/index.js +28 -0
- package/lib/types/points.d.ts +28 -0
- package/lib/types/points.js +3 -0
- package/lib/types/pools.d.ts +144 -0
- package/lib/types/pools.js +3 -0
- package/lib/types/staking.d.ts +28 -0
- package/lib/types/staking.js +3 -0
- package/lib/types/sub-accounts.d.ts +150 -0
- package/lib/types/sub-accounts.js +3 -0
- package/lib/types/subgraph.d.ts +84 -0
- package/lib/types/subgraph.js +3 -0
- package/lib/types/typed-contract.d.ts +102 -0
- package/lib/types/typed-contract.js +3 -0
- package/lib/types/user.d.ts +1 -0
- package/lib/types/user.js +3 -0
- package/lib/types/vaults.d.ts +886 -0
- package/lib/types/vaults.js +30 -0
- package/lib/types/web3.d.ts +81 -0
- package/lib/types/web3.js +14 -0
- package/lib/types/webserver.d.ts +730 -0
- package/lib/types/webserver.js +3 -0
- package/package.json +78 -3
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { type Connection, PublicKey } from '@solana/web3.js';
|
|
2
|
+
import type { IAddress, ISolanaNetwork, IVaultAvailableRedemption } from '../../types';
|
|
3
|
+
import { VaultRedemptionStatus } from '../../types/vaults';
|
|
4
|
+
import type { IVaultWithdrawalQueue } from '../../types/vaults';
|
|
5
|
+
import type { ISolanaVaultState, ISolanaWithdrawalRequestState } from './types';
|
|
6
|
+
/**
|
|
7
|
+
* The queue PDA for a vault: `["withdrawal_queue", vault_state]` under the queue
|
|
8
|
+
* program. The vault only ever attaches this address.
|
|
9
|
+
*
|
|
10
|
+
* @param vaultState - The vault's `VaultState` account.
|
|
11
|
+
* @param queueProgramId - The august_withdrawal_queue program id for the network.
|
|
12
|
+
*/
|
|
13
|
+
export declare function deriveWithdrawalQueuePda(vaultState: PublicKey, queueProgramId: PublicKey): PublicKey;
|
|
14
|
+
/**
|
|
15
|
+
* Where a request stands at `nowSeconds`, by the program's own rules
|
|
16
|
+
* (`WithdrawalRequest::is_expired` / `is_eligible`): a non-zero `expiresAt` at
|
|
17
|
+
* or before now is expired, and that is checked first because an expired
|
|
18
|
+
* request can only be cancelled; otherwise it is claimable from `eligibleAt`.
|
|
19
|
+
*
|
|
20
|
+
* @param request - Decoded request; `eligibleAt` / `expiresAt` in Unix seconds.
|
|
21
|
+
* @param nowSeconds - Unix seconds. Wall-clock time stands in for the chain's
|
|
22
|
+
* clock, so a request within seconds of a boundary may be classified a slot
|
|
23
|
+
* early or late.
|
|
24
|
+
*/
|
|
25
|
+
export declare function classifyWithdrawalRequest(request: Pick<ISolanaWithdrawalRequestState, 'eligibleAt' | 'expiresAt'>, nowSeconds: number): VaultRedemptionStatus;
|
|
26
|
+
/**
|
|
27
|
+
* What finalizing `shares` would pay the recipient at the vault's current
|
|
28
|
+
* state: the offset-aware `assets_for_redeem`, less the ceil-rounded
|
|
29
|
+
* withdrawal fee. Finalize prices at execution, so this is an estimate.
|
|
30
|
+
*
|
|
31
|
+
* @returns Raw deposit-mint units, net of fee.
|
|
32
|
+
* @throws UpshiftValidationError when the vault has no share price.
|
|
33
|
+
*/
|
|
34
|
+
export declare function estimateRequestPayout(input: {
|
|
35
|
+
vaultState: Pick<ISolanaVaultState, 'localAum' | 'deployedAum' | 'withdrawalFee' | 'shareOffset'>;
|
|
36
|
+
supply: bigint;
|
|
37
|
+
shares: bigint;
|
|
38
|
+
}): bigint;
|
|
39
|
+
/**
|
|
40
|
+
* The withdrawal queue program id a Solana service names, or `undefined` when
|
|
41
|
+
* it names none: the queue is not deployed on its network, or the service has
|
|
42
|
+
* neither `network` nor `getProgramId`. Read
|
|
43
|
+
* paths treat that as "no queue" rather than a failed read, so they make no RPC
|
|
44
|
+
* call and log nothing.
|
|
45
|
+
*
|
|
46
|
+
* Prefers `network`, read straight from `programIds`: `getProgramId` is an
|
|
47
|
+
* instrumented public method, and calling it where it throws by design would
|
|
48
|
+
* record an error breadcrumb on every vault read.
|
|
49
|
+
*
|
|
50
|
+
* @param service - The SolanaAdapter (or a stand-in) the read was given.
|
|
51
|
+
* @returns The queue program id, or `undefined`.
|
|
52
|
+
* @throws When the service names a malformed id; callers read inside their
|
|
53
|
+
* own `try`, so that is logged as a failed queue read.
|
|
54
|
+
*/
|
|
55
|
+
export declare function resolveQueueProgramId(service: {
|
|
56
|
+
network?: ISolanaNetwork;
|
|
57
|
+
getProgramId?: (type: 'vault' | 'withdrawalQueue') => string;
|
|
58
|
+
}): PublicKey | undefined;
|
|
59
|
+
/**
|
|
60
|
+
* The vault's withdrawal queue summary for `IVault.withdrawalQueue`, or
|
|
61
|
+
* `undefined` when the vault has no queue.
|
|
62
|
+
*
|
|
63
|
+
* `enabled` is whether the vault's redeem gate points at this queue, read from
|
|
64
|
+
* the vault state in the same call as the queue, so an attach or release shows
|
|
65
|
+
* at once rather than when a cached vault state expires. A queue that was
|
|
66
|
+
* released keeps its account and may still hold pending requests, so it is
|
|
67
|
+
* reported with `enabled: false`.
|
|
68
|
+
*
|
|
69
|
+
* RPC: one `getMultipleAccountsInfo` (the queue and the vault state). Not
|
|
70
|
+
* cached: the counters change with every request.
|
|
71
|
+
*
|
|
72
|
+
* @param input - The vault and where to read.
|
|
73
|
+
*/
|
|
74
|
+
export declare function getSolanaWithdrawalQueueSummary(input: {
|
|
75
|
+
connection: Connection;
|
|
76
|
+
queueProgramId: PublicKey;
|
|
77
|
+
/** The vault's `VaultState` account. */
|
|
78
|
+
vaultState: PublicKey;
|
|
79
|
+
/** Decimals of the vault's share mint, for `pendingShares`. */
|
|
80
|
+
shareDecimals: number;
|
|
81
|
+
}): Promise<IVaultWithdrawalQueue | undefined>;
|
|
82
|
+
/**
|
|
83
|
+
* `owner`'s pending requests on a vault's queue, split the way the EVM path
|
|
84
|
+
* splits them: `availableRedemptions` holds requests still waiting
|
|
85
|
+
* (`AWAITING_COOLDOWN`) or past their window (`EXPIRED`, cancel-only);
|
|
86
|
+
* `pendingRedemptions` holds requests finalizable now (`READY_TO_CLAIM`).
|
|
87
|
+
*
|
|
88
|
+
* Each entry's `amount` is the escrowed shares and `estimatedAssets` the net
|
|
89
|
+
* payout at the current share price (see {@link estimateRequestPayout}),
|
|
90
|
+
* priced from the vault state and share supply of a single slot, never from a
|
|
91
|
+
* cached state. `receiver` is the wallet that owns the request's payout token
|
|
92
|
+
* account, which need not be the requester; if that account is gone it is the
|
|
93
|
+
* account address itself. `id` and `hash` are the request account's address:
|
|
94
|
+
* the program keeps no creation transaction to point at. `date` and
|
|
95
|
+
* `day` / `month` / `year` are the eligibility time (UTC); `timestamp` is when
|
|
96
|
+
* the request was made.
|
|
97
|
+
*
|
|
98
|
+
* RPC, worst case: one `getAccountInfo` (skipped once the queue is known to
|
|
99
|
+
* exist), one `getProgramAccounts` filtered on queue and owner, and, when the
|
|
100
|
+
* owner has any request, one `getMultipleAccountsInfo` carrying the vault
|
|
101
|
+
* state, share mint and up to 98 distinct payout accounts. Each further 100
|
|
102
|
+
* distinct payout accounts cost one more `getMultipleAccountsInfo`, at most
|
|
103
|
+
* four in flight. A vault without a queue costs the single `getAccountInfo`.
|
|
104
|
+
*
|
|
105
|
+
* @param input - The vault, the owner, and where to read.
|
|
106
|
+
*/
|
|
107
|
+
export declare function getSolanaWithdrawalRedemptions(input: {
|
|
108
|
+
connection: Connection;
|
|
109
|
+
queueProgramId: PublicKey;
|
|
110
|
+
/** The vault's `VaultState` account, read fresh for pricing. */
|
|
111
|
+
vaultStateAddress: PublicKey;
|
|
112
|
+
/** The vault's share mint, read in the same call for the supply. */
|
|
113
|
+
shareMint: PublicKey;
|
|
114
|
+
/** The holder whose requests to list. */
|
|
115
|
+
owner: PublicKey;
|
|
116
|
+
/** The vault address to stamp on each entry. */
|
|
117
|
+
vault: IAddress;
|
|
118
|
+
/** Deposit mint decimals, for `estimatedAssets`. */
|
|
119
|
+
depositDecimals: number;
|
|
120
|
+
/** Unix seconds to classify against; defaults to now. */
|
|
121
|
+
nowSeconds?: number;
|
|
122
|
+
}): Promise<{
|
|
123
|
+
availableRedemptions: IVaultAvailableRedemption[];
|
|
124
|
+
pendingRedemptions: IVaultAvailableRedemption[];
|
|
125
|
+
}>;
|
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.deriveWithdrawalQueuePda = deriveWithdrawalQueuePda;
|
|
4
|
+
exports.classifyWithdrawalRequest = classifyWithdrawalRequest;
|
|
5
|
+
exports.estimateRequestPayout = estimateRequestPayout;
|
|
6
|
+
exports.resolveQueueProgramId = resolveQueueProgramId;
|
|
7
|
+
exports.getSolanaWithdrawalQueueSummary = getSolanaWithdrawalQueueSummary;
|
|
8
|
+
exports.getSolanaWithdrawalRedemptions = getSolanaWithdrawalRedemptions;
|
|
9
|
+
/**
|
|
10
|
+
* Read paths for the august_withdrawal_queue program: the per-vault queue
|
|
11
|
+
* summary and a holder's pending withdrawal requests.
|
|
12
|
+
*
|
|
13
|
+
* Internal to the SDK. `getSolanaVault` uses {@link getSolanaWithdrawalQueueSummary};
|
|
14
|
+
* `getVaultPositions` and `getVaultAvailableRedemptions` use
|
|
15
|
+
* {@link getSolanaWithdrawalRedemptions}. Nothing here signs or writes.
|
|
16
|
+
*/
|
|
17
|
+
const anchor_1 = require("@coral-xyz/anchor");
|
|
18
|
+
const spl_token_1 = require("@solana/spl-token");
|
|
19
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
20
|
+
const core_1 = require("../../core");
|
|
21
|
+
const cache_1 = require("../../core/cache");
|
|
22
|
+
const concurrency_1 = require("../../core/helpers/concurrency");
|
|
23
|
+
const vaults_1 = require("../../types/vaults");
|
|
24
|
+
const vault_idl_1 = require("./idl/vault-idl");
|
|
25
|
+
const withdrawal_queue_idl_1 = require("./idl/withdrawal-queue-idl");
|
|
26
|
+
const pricing_1 = require("./pricing");
|
|
27
|
+
const constants_1 = require("./constants");
|
|
28
|
+
const utils_1 = require("./utils");
|
|
29
|
+
const token_reads_1 = require("./token-reads");
|
|
30
|
+
const WITHDRAWAL_QUEUE_SEED = 'withdrawal_queue';
|
|
31
|
+
/** Byte offsets of `queue` and `owner` in a `WithdrawalRequest`, after the 8-byte discriminator. */
|
|
32
|
+
const REQUEST_QUEUE_OFFSET = 8;
|
|
33
|
+
const REQUEST_OWNER_OFFSET = 40;
|
|
34
|
+
/** `getMultipleAccountsInfo` accepts at most this many accounts per call. */
|
|
35
|
+
const MAX_ACCOUNTS_PER_CALL = 100;
|
|
36
|
+
/** Payout-account batches beyond the first, in flight at once. */
|
|
37
|
+
const PAYOUT_BATCH_CONCURRENCY = 4;
|
|
38
|
+
/**
|
|
39
|
+
* The queue PDA for a vault: `["withdrawal_queue", vault_state]` under the queue
|
|
40
|
+
* program. The vault only ever attaches this address.
|
|
41
|
+
*
|
|
42
|
+
* @param vaultState - The vault's `VaultState` account.
|
|
43
|
+
* @param queueProgramId - The august_withdrawal_queue program id for the network.
|
|
44
|
+
*/
|
|
45
|
+
function deriveWithdrawalQueuePda(vaultState, queueProgramId) {
|
|
46
|
+
return web3_js_1.PublicKey.findProgramAddressSync([Buffer.from(WITHDRAWAL_QUEUE_SEED), vaultState.toBuffer()], queueProgramId)[0];
|
|
47
|
+
}
|
|
48
|
+
/** A read-only queue program client on `connection`. No wallet, no RPC on construction. */
|
|
49
|
+
function queueProgram(connection, queueProgramId) {
|
|
50
|
+
return new anchor_1.Program({ ...withdrawal_queue_idl_1.withdrawalQueueIdl, address: queueProgramId.toBase58() }, utils_1.SolanaUtils.getReadOnlyProvider({ connection }));
|
|
51
|
+
}
|
|
52
|
+
/** A read-only vault program client, used only for its account coder. */
|
|
53
|
+
function vaultProgram(connection) {
|
|
54
|
+
return new anchor_1.Program(vault_idl_1.vaultIdl, utils_1.SolanaUtils.getReadOnlyProvider({ connection }));
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Where a request stands at `nowSeconds`, by the program's own rules
|
|
58
|
+
* (`WithdrawalRequest::is_expired` / `is_eligible`): a non-zero `expiresAt` at
|
|
59
|
+
* or before now is expired, and that is checked first because an expired
|
|
60
|
+
* request can only be cancelled; otherwise it is claimable from `eligibleAt`.
|
|
61
|
+
*
|
|
62
|
+
* @param request - Decoded request; `eligibleAt` / `expiresAt` in Unix seconds.
|
|
63
|
+
* @param nowSeconds - Unix seconds. Wall-clock time stands in for the chain's
|
|
64
|
+
* clock, so a request within seconds of a boundary may be classified a slot
|
|
65
|
+
* early or late.
|
|
66
|
+
*/
|
|
67
|
+
function classifyWithdrawalRequest(request, nowSeconds) {
|
|
68
|
+
const expiresAt = BigInt(request.expiresAt.toString());
|
|
69
|
+
const now = BigInt(nowSeconds);
|
|
70
|
+
if (expiresAt !== 0n && now >= expiresAt) {
|
|
71
|
+
return vaults_1.VaultRedemptionStatus.EXPIRED;
|
|
72
|
+
}
|
|
73
|
+
if (now >= BigInt(request.eligibleAt.toString())) {
|
|
74
|
+
return vaults_1.VaultRedemptionStatus.READY_TO_CLAIM;
|
|
75
|
+
}
|
|
76
|
+
return vaults_1.VaultRedemptionStatus.AWAITING_COOLDOWN;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* What finalizing `shares` would pay the recipient at the vault's current
|
|
80
|
+
* state: the offset-aware `assets_for_redeem`, less the ceil-rounded
|
|
81
|
+
* withdrawal fee. Finalize prices at execution, so this is an estimate.
|
|
82
|
+
*
|
|
83
|
+
* @returns Raw deposit-mint units, net of fee.
|
|
84
|
+
* @throws UpshiftValidationError when the vault has no share price.
|
|
85
|
+
*/
|
|
86
|
+
function estimateRequestPayout(input) {
|
|
87
|
+
const { vaultState, supply, shares } = input;
|
|
88
|
+
const gross = (0, pricing_1.assetsForRedeem)({
|
|
89
|
+
supply,
|
|
90
|
+
totalAssets: (0, pricing_1.totalAssetsOf)(vaultState),
|
|
91
|
+
shares,
|
|
92
|
+
offset: (0, pricing_1.resolveShareOffset)(vaultState.shareOffset),
|
|
93
|
+
});
|
|
94
|
+
return (gross -
|
|
95
|
+
(0, pricing_1.withdrawalFee)(gross, (0, pricing_1.toBigInt)(vaultState.withdrawalFee, 'withdrawalFee')));
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Whether the vault's queue account exists, remembering a yes. A queue is never
|
|
99
|
+
* closed once created (release keeps it so the vault can re-attach), so a
|
|
100
|
+
* positive answer is safe to cache; a negative one is not, and costs one
|
|
101
|
+
* `getAccountInfo` each time.
|
|
102
|
+
*/
|
|
103
|
+
async function queueExists(connection, queue) {
|
|
104
|
+
const cacheKey = `withdrawalQueueExists-${queue.toBase58()}`;
|
|
105
|
+
if (await (0, cache_1.getSafeCache)(cacheKey))
|
|
106
|
+
return true;
|
|
107
|
+
const exists = (await connection.getAccountInfo(queue)) !== null;
|
|
108
|
+
if (exists)
|
|
109
|
+
await (0, cache_1.setSafeCache)(cacheKey, true);
|
|
110
|
+
return exists;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* The wallet a request pays: the owner (authority) of its payout token account.
|
|
114
|
+
* A request may pay someone other than its requester, so this is read from the
|
|
115
|
+
* account rather than assumed. If the account is gone or is not a token
|
|
116
|
+
* account, its address is the best identification there is, and is returned
|
|
117
|
+
* as is; finalizing such a request would fail until the account is restored.
|
|
118
|
+
*/
|
|
119
|
+
function payoutWallet(tokenAccount, info) {
|
|
120
|
+
if (!info)
|
|
121
|
+
return tokenAccount.toBase58();
|
|
122
|
+
try {
|
|
123
|
+
return (0, spl_token_1.unpackAccount)(tokenAccount, info, info.owner).owner.toBase58();
|
|
124
|
+
}
|
|
125
|
+
catch {
|
|
126
|
+
return tokenAccount.toBase58();
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* The withdrawal queue program id a Solana service names, or `undefined` when
|
|
131
|
+
* it names none: the queue is not deployed on its network, or the service has
|
|
132
|
+
* neither `network` nor `getProgramId`. Read
|
|
133
|
+
* paths treat that as "no queue" rather than a failed read, so they make no RPC
|
|
134
|
+
* call and log nothing.
|
|
135
|
+
*
|
|
136
|
+
* Prefers `network`, read straight from `programIds`: `getProgramId` is an
|
|
137
|
+
* instrumented public method, and calling it where it throws by design would
|
|
138
|
+
* record an error breadcrumb on every vault read.
|
|
139
|
+
*
|
|
140
|
+
* @param service - The SolanaAdapter (or a stand-in) the read was given.
|
|
141
|
+
* @returns The queue program id, or `undefined`.
|
|
142
|
+
* @throws When the service names a malformed id; callers read inside their
|
|
143
|
+
* own `try`, so that is logged as a failed queue read.
|
|
144
|
+
*/
|
|
145
|
+
function resolveQueueProgramId(service) {
|
|
146
|
+
if (service.network) {
|
|
147
|
+
const id = (0, constants_1.getDeployedProgramIds)(service.network)?.withdrawalQueue;
|
|
148
|
+
return id ? new web3_js_1.PublicKey(id) : undefined;
|
|
149
|
+
}
|
|
150
|
+
if (!service.getProgramId)
|
|
151
|
+
return undefined;
|
|
152
|
+
try {
|
|
153
|
+
return new web3_js_1.PublicKey(service.getProgramId('withdrawalQueue'));
|
|
154
|
+
}
|
|
155
|
+
catch (error) {
|
|
156
|
+
if (error instanceof core_1.UpshiftValidationError)
|
|
157
|
+
return undefined;
|
|
158
|
+
throw error;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* The vault's withdrawal queue summary for `IVault.withdrawalQueue`, or
|
|
163
|
+
* `undefined` when the vault has no queue.
|
|
164
|
+
*
|
|
165
|
+
* `enabled` is whether the vault's redeem gate points at this queue, read from
|
|
166
|
+
* the vault state in the same call as the queue, so an attach or release shows
|
|
167
|
+
* at once rather than when a cached vault state expires. A queue that was
|
|
168
|
+
* released keeps its account and may still hold pending requests, so it is
|
|
169
|
+
* reported with `enabled: false`.
|
|
170
|
+
*
|
|
171
|
+
* RPC: one `getMultipleAccountsInfo` (the queue and the vault state). Not
|
|
172
|
+
* cached: the counters change with every request.
|
|
173
|
+
*
|
|
174
|
+
* @param input - The vault and where to read.
|
|
175
|
+
*/
|
|
176
|
+
async function getSolanaWithdrawalQueueSummary(input) {
|
|
177
|
+
const queue = deriveWithdrawalQueuePda(input.vaultState, input.queueProgramId);
|
|
178
|
+
const [queueInfo, vaultStateInfo] = await input.connection.getMultipleAccountsInfo([queue, input.vaultState]);
|
|
179
|
+
if (!queueInfo || !vaultStateInfo)
|
|
180
|
+
return undefined;
|
|
181
|
+
// Decoded by name, so an account of another type at either address throws
|
|
182
|
+
// rather than being read as this one.
|
|
183
|
+
const state = queueProgram(input.connection, input.queueProgramId).coder.accounts.decode('withdrawalQueue', queueInfo.data);
|
|
184
|
+
const gate = vaultProgram(input.connection).coder.accounts.decode('vaultState', vaultStateInfo.data).withdrawalQueueAuthority;
|
|
185
|
+
return {
|
|
186
|
+
address: queue.toBase58(),
|
|
187
|
+
enabled: gate ? new web3_js_1.PublicKey(gate).equals(queue) : false,
|
|
188
|
+
cooldownSeconds: state.cooldownSeconds.toNumber(),
|
|
189
|
+
fulfillmentWindowSeconds: state.fulfillmentWindowSeconds.toNumber(),
|
|
190
|
+
pendingCount: state.pendingRequests.toNumber(),
|
|
191
|
+
pendingShares: (0, core_1.toNormalizedBn)(BigInt(state.pendingShares.toString()), input.shareDecimals),
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* `owner`'s pending requests on a vault's queue, split the way the EVM path
|
|
196
|
+
* splits them: `availableRedemptions` holds requests still waiting
|
|
197
|
+
* (`AWAITING_COOLDOWN`) or past their window (`EXPIRED`, cancel-only);
|
|
198
|
+
* `pendingRedemptions` holds requests finalizable now (`READY_TO_CLAIM`).
|
|
199
|
+
*
|
|
200
|
+
* Each entry's `amount` is the escrowed shares and `estimatedAssets` the net
|
|
201
|
+
* payout at the current share price (see {@link estimateRequestPayout}),
|
|
202
|
+
* priced from the vault state and share supply of a single slot, never from a
|
|
203
|
+
* cached state. `receiver` is the wallet that owns the request's payout token
|
|
204
|
+
* account, which need not be the requester; if that account is gone it is the
|
|
205
|
+
* account address itself. `id` and `hash` are the request account's address:
|
|
206
|
+
* the program keeps no creation transaction to point at. `date` and
|
|
207
|
+
* `day` / `month` / `year` are the eligibility time (UTC); `timestamp` is when
|
|
208
|
+
* the request was made.
|
|
209
|
+
*
|
|
210
|
+
* RPC, worst case: one `getAccountInfo` (skipped once the queue is known to
|
|
211
|
+
* exist), one `getProgramAccounts` filtered on queue and owner, and, when the
|
|
212
|
+
* owner has any request, one `getMultipleAccountsInfo` carrying the vault
|
|
213
|
+
* state, share mint and up to 98 distinct payout accounts. Each further 100
|
|
214
|
+
* distinct payout accounts cost one more `getMultipleAccountsInfo`, at most
|
|
215
|
+
* four in flight. A vault without a queue costs the single `getAccountInfo`.
|
|
216
|
+
*
|
|
217
|
+
* @param input - The vault, the owner, and where to read.
|
|
218
|
+
*/
|
|
219
|
+
async function getSolanaWithdrawalRedemptions(input) {
|
|
220
|
+
const availableRedemptions = [];
|
|
221
|
+
const pendingRedemptions = [];
|
|
222
|
+
const queue = deriveWithdrawalQueuePda(input.vaultStateAddress, input.queueProgramId);
|
|
223
|
+
if (!(await queueExists(input.connection, queue))) {
|
|
224
|
+
return { availableRedemptions, pendingRedemptions };
|
|
225
|
+
}
|
|
226
|
+
const requests = await queueProgram(input.connection, input.queueProgramId).account.withdrawalRequest.all([
|
|
227
|
+
{ memcmp: { offset: REQUEST_QUEUE_OFFSET, bytes: queue.toBase58() } },
|
|
228
|
+
{ memcmp: { offset: REQUEST_OWNER_OFFSET, bytes: input.owner.toBase58() } },
|
|
229
|
+
]);
|
|
230
|
+
if (requests.length === 0) {
|
|
231
|
+
return { availableRedemptions, pendingRedemptions };
|
|
232
|
+
}
|
|
233
|
+
// Payout accounts, deduplicated: requests often share one. The first batch
|
|
234
|
+
// rides with the vault state and share mint, which must share a slot to
|
|
235
|
+
// price coherently; the rest only name receivers, so they need not.
|
|
236
|
+
const payoutAccounts = [
|
|
237
|
+
...new Map(requests.map(({ account }) => [
|
|
238
|
+
account.recipientTokenAccount.toBase58(),
|
|
239
|
+
account.recipientTokenAccount,
|
|
240
|
+
])).values(),
|
|
241
|
+
];
|
|
242
|
+
const firstBatch = payoutAccounts.slice(0, MAX_ACCOUNTS_PER_CALL - 2);
|
|
243
|
+
const laterBatches = [];
|
|
244
|
+
for (let i = firstBatch.length; i < payoutAccounts.length; i += MAX_ACCOUNTS_PER_CALL) {
|
|
245
|
+
laterBatches.push(payoutAccounts.slice(i, i + MAX_ACCOUNTS_PER_CALL));
|
|
246
|
+
}
|
|
247
|
+
const [snapshot, laterInfos] = await Promise.all([
|
|
248
|
+
(0, token_reads_1.readPricingSnapshot)({
|
|
249
|
+
connection: input.connection,
|
|
250
|
+
program: vaultProgram(input.connection),
|
|
251
|
+
vaultStatePda: input.vaultStateAddress,
|
|
252
|
+
shareMintAddr: input.shareMint,
|
|
253
|
+
extraAccounts: firstBatch,
|
|
254
|
+
}),
|
|
255
|
+
(0, concurrency_1.mapWithConcurrency)(laterBatches, PAYOUT_BATCH_CONCURRENCY, (batch) => input.connection.getMultipleAccountsInfo(batch)),
|
|
256
|
+
]);
|
|
257
|
+
const { vaultStateData, supply, shareDecimals } = snapshot;
|
|
258
|
+
const payoutInfos = [...snapshot.extraAccountInfos, ...laterInfos.flat()];
|
|
259
|
+
const payoutInfoOf = new Map(payoutAccounts.map((address, i) => [address.toBase58(), payoutInfos[i]]));
|
|
260
|
+
const now = input.nowSeconds ?? Math.floor(Date.now() / 1000);
|
|
261
|
+
for (const { publicKey, account } of requests) {
|
|
262
|
+
const shares = BigInt(account.shares.toString());
|
|
263
|
+
const eligibleAt = account.eligibleAt.toNumber();
|
|
264
|
+
const date = new Date(eligibleAt * 1000);
|
|
265
|
+
const status = classifyWithdrawalRequest(account, now);
|
|
266
|
+
let estimatedAssets;
|
|
267
|
+
try {
|
|
268
|
+
estimatedAssets = (0, core_1.toNormalizedBn)(estimateRequestPayout({ vaultState: vaultStateData, supply, shares }), input.depositDecimals);
|
|
269
|
+
}
|
|
270
|
+
catch (error) {
|
|
271
|
+
// A vault with no share price (assets zero against outstanding shares)
|
|
272
|
+
// has nothing to quote; the request itself is still listed.
|
|
273
|
+
core_1.Logger.log.warn('getSolanaWithdrawalRedemptions', 'No payout estimate', {
|
|
274
|
+
request: publicKey.toBase58(),
|
|
275
|
+
error,
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
const entry = {
|
|
279
|
+
id: publicKey.toBase58(),
|
|
280
|
+
hash: publicKey.toBase58(),
|
|
281
|
+
timestamp: account.requestedAt.toNumber(),
|
|
282
|
+
receiver: payoutWallet(account.recipientTokenAccount, payoutInfoOf.get(account.recipientTokenAccount.toBase58()) ?? null),
|
|
283
|
+
day: (0, core_1.toNormalizedBn)(date.getUTCDate(), 0),
|
|
284
|
+
month: (0, core_1.toNormalizedBn)(date.getUTCMonth() + 1, 0),
|
|
285
|
+
year: (0, core_1.toNormalizedBn)(date.getUTCFullYear(), 0),
|
|
286
|
+
amount: (0, core_1.toNormalizedBn)(shares, shareDecimals),
|
|
287
|
+
date,
|
|
288
|
+
vault: input.vault,
|
|
289
|
+
status,
|
|
290
|
+
...(estimatedAssets && { estimatedAssets }),
|
|
291
|
+
};
|
|
292
|
+
if (status === vaults_1.VaultRedemptionStatus.READY_TO_CLAIM) {
|
|
293
|
+
pendingRedemptions.push(entry);
|
|
294
|
+
}
|
|
295
|
+
else {
|
|
296
|
+
availableRedemptions.push(entry);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
return { availableRedemptions, pendingRedemptions };
|
|
300
|
+
}
|
|
301
|
+
//# sourceMappingURL=withdrawal-queue.js.map
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stellar Vault Actions
|
|
3
|
+
*
|
|
4
|
+
* Builds unsigned Soroban transactions for vault deposit/redeem operations.
|
|
5
|
+
* Returns assembled XDR (base64) for wallet signing (e.g. Freighter).
|
|
6
|
+
*/
|
|
7
|
+
import type { IStellarDepositParams, IStellarRedeemParams } from './types';
|
|
8
|
+
/**
|
|
9
|
+
* Deposit assets into a Stellar vault (self-deposit).
|
|
10
|
+
*
|
|
11
|
+
* Builds an unsigned Soroban transaction invoking the vault's `deposit` function.
|
|
12
|
+
* All three address roles (receiver, from, operator) are set to senderAddress.
|
|
13
|
+
*
|
|
14
|
+
* Contract signature: deposit(assets: i128, receiver: Address, from: Address, operator: Address) -> i128
|
|
15
|
+
*
|
|
16
|
+
* @returns Base64-encoded XDR of the unsigned transaction, ready for wallet signing.
|
|
17
|
+
*/
|
|
18
|
+
export declare function handleStellarDeposit(params: IStellarDepositParams): Promise<string>;
|
|
19
|
+
/**
|
|
20
|
+
* Build an unsigned self-redeem Soroban transaction (receiver, owner, and
|
|
21
|
+
* operator all = `receiverAddress`). Assumes the deployed vault exposes
|
|
22
|
+
* `redeem(shares: i128, receiver, owner, operator) -> i128`; divergence
|
|
23
|
+
* surfaces as a generic Soroban simulation error.
|
|
24
|
+
*
|
|
25
|
+
* Side effect on failure: when the *vault* cannot serve the redemption — it
|
|
26
|
+
* rejected the call, or its ledger state needs restoring — the failure is
|
|
27
|
+
* reported to that vault's curator. Stellar vaults are instant-redeem only, so
|
|
28
|
+
* this is the curator's only signal that their depositors cannot get out.
|
|
29
|
+
* Fire-and-forget and deduped; see
|
|
30
|
+
* {@link reportRedeemFailure} and {@link REPORTED_BUILD_STAGES}.
|
|
31
|
+
*
|
|
32
|
+
* Note this includes a caller-caused rejection such as redeeming more shares
|
|
33
|
+
* than the wallet holds: the contract trapping is what we can observe, and
|
|
34
|
+
* telling that apart from a vault-side problem needs the vault's error
|
|
35
|
+
* taxonomy. A bad address, an unfunded account, and an exhausted RPC failover
|
|
36
|
+
* are excluded — none of those reached the vault.
|
|
37
|
+
*
|
|
38
|
+
* @returns Base64-encoded XDR ready for wallet signing; pass the signed
|
|
39
|
+
* XDR to {@link submitStellarTransaction}.
|
|
40
|
+
*/
|
|
41
|
+
export declare function handleStellarRedeem(params: IStellarRedeemParams): Promise<string>;
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Stellar Vault Actions
|
|
4
|
+
*
|
|
5
|
+
* Builds unsigned Soroban transactions for vault deposit/redeem operations.
|
|
6
|
+
* Returns assembled XDR (base64) for wallet signing (e.g. Freighter).
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.handleStellarDeposit = handleStellarDeposit;
|
|
10
|
+
exports.handleStellarRedeem = handleStellarRedeem;
|
|
11
|
+
const stellar_sdk_1 = require("@stellar/stellar-sdk");
|
|
12
|
+
const soroban_1 = require("./soroban");
|
|
13
|
+
const utils_1 = require("./utils");
|
|
14
|
+
const core_1 = require("../../core");
|
|
15
|
+
const curator_alert_1 = require("../../core/logger/curator-alert");
|
|
16
|
+
/**
|
|
17
|
+
* Build failures that mean the *vault* cannot serve a redemption right now, as
|
|
18
|
+
* opposed to a caller problem or a transport problem.
|
|
19
|
+
*
|
|
20
|
+
* `simulation` is the contract rejecting the call. `restore-required` is its
|
|
21
|
+
* ledger state having been archived, which blocks every redemption on the vault
|
|
22
|
+
* until someone submits a restore footprint — different remedy, same
|
|
23
|
+
* consequence for a depositor trying to get out.
|
|
24
|
+
*
|
|
25
|
+
* Deliberately excluded: `rpc-failover` (our transport, not their vault),
|
|
26
|
+
* `assembly` (an SDK-side fault), and validation errors, which carry no stage
|
|
27
|
+
* at all.
|
|
28
|
+
*/
|
|
29
|
+
const REPORTED_BUILD_STAGES = new Set(['simulation', 'restore-required']);
|
|
30
|
+
function validateContractAddress(contractId) {
|
|
31
|
+
if (!(0, utils_1.isStellarAddress)(contractId) || contractId[0] !== 'C') {
|
|
32
|
+
throw new core_1.UpshiftValidationError('INVALID_ADDRESS', `Invalid contract address: expected a Stellar contract (C-prefix), got "${contractId}"`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function validateAccountAddress(address, label) {
|
|
36
|
+
if (!(0, utils_1.isStellarAddress)(address) || address[0] !== 'G') {
|
|
37
|
+
throw new core_1.UpshiftValidationError('INVALID_ADDRESS', `Invalid ${label} address: expected a Stellar account (G-prefix), got "${address}"`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Build a self-operation Soroban transaction where all address roles
|
|
42
|
+
* (receiver, from/owner, operator) are set to the same user address.
|
|
43
|
+
*
|
|
44
|
+
* Note: This only supports self-operations. If delegated operations
|
|
45
|
+
* (distinct receiver/owner/operator) are needed in the future,
|
|
46
|
+
* a separate argument builder will be required.
|
|
47
|
+
*/
|
|
48
|
+
function buildSelfOperationArgs(amount, userAddress) {
|
|
49
|
+
const userScVal = new stellar_sdk_1.Address(userAddress).toScVal();
|
|
50
|
+
return [
|
|
51
|
+
(0, stellar_sdk_1.nativeToScVal)(amount, { type: 'i128' }),
|
|
52
|
+
userScVal,
|
|
53
|
+
userScVal,
|
|
54
|
+
userScVal,
|
|
55
|
+
];
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Deposit assets into a Stellar vault (self-deposit).
|
|
59
|
+
*
|
|
60
|
+
* Builds an unsigned Soroban transaction invoking the vault's `deposit` function.
|
|
61
|
+
* All three address roles (receiver, from, operator) are set to senderAddress.
|
|
62
|
+
*
|
|
63
|
+
* Contract signature: deposit(assets: i128, receiver: Address, from: Address, operator: Address) -> i128
|
|
64
|
+
*
|
|
65
|
+
* @returns Base64-encoded XDR of the unsigned transaction, ready for wallet signing.
|
|
66
|
+
*/
|
|
67
|
+
async function handleStellarDeposit(params) {
|
|
68
|
+
const { contractId, amount, senderAddress, network, sorobanRpcUrl } = params;
|
|
69
|
+
validateContractAddress(contractId);
|
|
70
|
+
validateAccountAddress(senderAddress, 'sender');
|
|
71
|
+
const config = (0, soroban_1.resolveNetworkConfig)(network, sorobanRpcUrl);
|
|
72
|
+
const args = buildSelfOperationArgs((0, soroban_1.toBigIntAmount)(amount, 'deposit amount'), senderAddress);
|
|
73
|
+
return (0, soroban_1.buildSorobanTx)(config, senderAddress, contractId, 'deposit', args);
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Build an unsigned self-redeem Soroban transaction (receiver, owner, and
|
|
77
|
+
* operator all = `receiverAddress`). Assumes the deployed vault exposes
|
|
78
|
+
* `redeem(shares: i128, receiver, owner, operator) -> i128`; divergence
|
|
79
|
+
* surfaces as a generic Soroban simulation error.
|
|
80
|
+
*
|
|
81
|
+
* Side effect on failure: when the *vault* cannot serve the redemption — it
|
|
82
|
+
* rejected the call, or its ledger state needs restoring — the failure is
|
|
83
|
+
* reported to that vault's curator. Stellar vaults are instant-redeem only, so
|
|
84
|
+
* this is the curator's only signal that their depositors cannot get out.
|
|
85
|
+
* Fire-and-forget and deduped; see
|
|
86
|
+
* {@link reportRedeemFailure} and {@link REPORTED_BUILD_STAGES}.
|
|
87
|
+
*
|
|
88
|
+
* Note this includes a caller-caused rejection such as redeeming more shares
|
|
89
|
+
* than the wallet holds: the contract trapping is what we can observe, and
|
|
90
|
+
* telling that apart from a vault-side problem needs the vault's error
|
|
91
|
+
* taxonomy. A bad address, an unfunded account, and an exhausted RPC failover
|
|
92
|
+
* are excluded — none of those reached the vault.
|
|
93
|
+
*
|
|
94
|
+
* @returns Base64-encoded XDR ready for wallet signing; pass the signed
|
|
95
|
+
* XDR to {@link submitStellarTransaction}.
|
|
96
|
+
*/
|
|
97
|
+
async function handleStellarRedeem(params) {
|
|
98
|
+
const { contractId, shares, receiverAddress, network, sorobanRpcUrl } = params;
|
|
99
|
+
validateContractAddress(contractId);
|
|
100
|
+
validateAccountAddress(receiverAddress, 'receiver');
|
|
101
|
+
const config = (0, soroban_1.resolveNetworkConfig)(network, sorobanRpcUrl);
|
|
102
|
+
// Normalized once and reused for both the invocation and the report: the
|
|
103
|
+
// caller's string may be any form `BigInt` accepts (`'0x10'`, `' 42 '`), and
|
|
104
|
+
// relaying that verbatim hands the reporting endpoint something it rejects.
|
|
105
|
+
const shareAmount = (0, soroban_1.toBigIntAmount)(shares, 'redeem shares');
|
|
106
|
+
const args = buildSelfOperationArgs(shareAmount, receiverAddress);
|
|
107
|
+
try {
|
|
108
|
+
return await (0, soroban_1.buildSorobanTx)(config, receiverAddress, contractId, 'redeem', args);
|
|
109
|
+
}
|
|
110
|
+
catch (err) {
|
|
111
|
+
if (err instanceof core_1.UpshiftSDKError &&
|
|
112
|
+
REPORTED_BUILD_STAGES.has(String(err.context?.stage))) {
|
|
113
|
+
(0, curator_alert_1.reportRedeemFailure)({
|
|
114
|
+
phase: 'simulation',
|
|
115
|
+
chain: 'stellar',
|
|
116
|
+
network,
|
|
117
|
+
contractId,
|
|
118
|
+
eoa: receiverAddress,
|
|
119
|
+
sharesRaw: shareAmount.toString(),
|
|
120
|
+
error: String(err.message),
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
throw err;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=actions.js.map
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stellar Constants
|
|
3
|
+
*/
|
|
4
|
+
import type { IStellarNetwork } from './types';
|
|
5
|
+
export declare const STELLAR_CHAIN_ID: number;
|
|
6
|
+
export declare const STELLAR_CHAIN: {
|
|
7
|
+
name: string;
|
|
8
|
+
chainId: number;
|
|
9
|
+
explorer: string;
|
|
10
|
+
};
|
|
11
|
+
export declare const SOROBAN_RPC_URLS: Record<IStellarNetwork, string>;
|
|
12
|
+
export declare const NETWORK_PASSPHRASES: Record<IStellarNetwork, string>;
|
|
13
|
+
export declare const STELLAR_FALLBACK_DECIMALS = 7;
|
|
14
|
+
/**
|
|
15
|
+
* Validity window for a submitted Soroban invocation (seconds).
|
|
16
|
+
*
|
|
17
|
+
* This becomes the transaction's `maxTime`. Validators reject a tx whose
|
|
18
|
+
* `maxTime` has passed (`txTOO_LATE`), so the window must outlast the slowest
|
|
19
|
+
* realistic sign-then-submit path: hardware wallets, careful manual review,
|
|
20
|
+
* and institutional approval flows (e.g. Fordefi) that don't sign instantly.
|
|
21
|
+
* 10 minutes comfortably covers those while staying well inside the Soroban
|
|
22
|
+
* footprint/ledger-entry TTL, so the simulated footprint can't go stale first.
|
|
23
|
+
*
|
|
24
|
+
* The window is anchored to the *network* clock (see `getNetworkCloseTime` in
|
|
25
|
+
* soroban.ts), not the signer's `Date.now()`, so a skewed device clock can't
|
|
26
|
+
* make the deadline expire early.
|
|
27
|
+
*/
|
|
28
|
+
export declare const TX_TIMEOUT_SECONDS = 600;
|
|
29
|
+
/** Timeout for read-only Soroban simulation queries (seconds). */
|
|
30
|
+
export declare const QUERY_TIMEOUT_SECONDS = 10;
|
|
31
|
+
/**
|
|
32
|
+
* Max fee ceiling in stroops (1_000_000 stroops = 0.1 XLM).
|
|
33
|
+
* assembleTransaction adjusts to the actual fee from simulation.
|
|
34
|
+
*/
|
|
35
|
+
export declare const MAX_FEE_STROOPS = "1000000";
|
|
36
|
+
/** Initial confirmation-poll interval (ms). Grows up to {@link POLL_INTERVAL_MAX_MS}. */
|
|
37
|
+
export declare const POLL_INTERVAL_MS = 2000;
|
|
38
|
+
/** Cap for the backed-off confirmation-poll interval (ms). */
|
|
39
|
+
export declare const POLL_INTERVAL_MAX_MS = 8000;
|
|
40
|
+
/** Multiplier applied to the poll interval after each NOT_FOUND poll. */
|
|
41
|
+
export declare const POLL_INTERVAL_BACKOFF = 1.5;
|
|
42
|
+
/** Maximum number of polling attempts before timeout. */
|
|
43
|
+
export declare const MAX_POLL_ATTEMPTS = 30;
|