upshift-finance 1.0.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 +349 -0
- 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 +1043 -0
- package/lib/abis/SwapRouter.js +740 -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 +209 -0
- package/lib/adapters/evm/index.d.ts +353 -0
- package/lib/adapters/evm/index.js +434 -0
- package/lib/adapters/evm/utils.d.ts +8 -0
- package/lib/adapters/evm/utils.js +51 -0
- package/lib/adapters/solana/constants.d.ts +33 -0
- package/lib/adapters/solana/constants.js +52 -0
- package/lib/adapters/solana/getters.d.ts +11 -0
- package/lib/adapters/solana/getters.js +165 -0
- package/lib/adapters/solana/idl/vault-idl.d.ts +272 -0
- package/lib/adapters/solana/idl/vault-idl.js +1084 -0
- package/lib/adapters/solana/index.d.ts +233 -0
- package/lib/adapters/solana/index.js +291 -0
- package/lib/adapters/solana/types.d.ts +67 -0
- package/lib/adapters/solana/types.js +3 -0
- package/lib/adapters/solana/utils.d.ts +141 -0
- package/lib/adapters/solana/utils.js +595 -0
- package/lib/adapters/solana/vault.actions.d.ts +57 -0
- package/lib/adapters/solana/vault.actions.js +379 -0
- package/lib/adapters/stellar/actions.d.ts +28 -0
- package/lib/adapters/stellar/actions.js +77 -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 +114 -0
- package/lib/adapters/stellar/index.js +175 -0
- package/lib/adapters/stellar/soroban.d.ts +123 -0
- package/lib/adapters/stellar/soroban.js +613 -0
- package/lib/adapters/stellar/submit.d.ts +34 -0
- package/lib/adapters/stellar/submit.js +149 -0
- package/lib/adapters/stellar/types.d.ts +58 -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 +14 -0
- package/lib/adapters/sui/constants.js +29 -0
- package/lib/adapters/sui/getters.d.ts +9 -0
- package/lib/adapters/sui/getters.js +60 -0
- package/lib/adapters/sui/index.d.ts +45 -0
- package/lib/adapters/sui/index.js +101 -0
- package/lib/adapters/sui/transformer.d.ts +10 -0
- package/lib/adapters/sui/transformer.js +107 -0
- package/lib/adapters/sui/types.d.ts +66 -0
- package/lib/adapters/sui/types.js +3 -0
- package/lib/adapters/sui/utils.d.ts +10 -0
- package/lib/adapters/sui/utils.js +29 -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 +5 -0
- package/lib/core/analytics/constants.js +9 -0
- package/lib/core/analytics/env.d.ts +29 -0
- package/lib/core/analytics/env.js +59 -0
- package/lib/core/analytics/index.d.ts +36 -0
- package/lib/core/analytics/index.js +79 -0
- package/lib/core/analytics/instrumentation.d.ts +29 -0
- package/lib/core/analytics/instrumentation.js +277 -0
- package/lib/core/analytics/method-taxonomy.d.ts +19 -0
- package/lib/core/analytics/method-taxonomy.js +128 -0
- package/lib/core/analytics/metrics.d.ts +33 -0
- package/lib/core/analytics/metrics.js +116 -0
- package/lib/core/analytics/sanitize.d.ts +44 -0
- package/lib/core/analytics/sanitize.js +260 -0
- package/lib/core/analytics/sentry-runtime.d.ts +15 -0
- package/lib/core/analytics/sentry-runtime.js +97 -0
- package/lib/core/analytics/sentry.d.ts +67 -0
- package/lib/core/analytics/sentry.js +613 -0
- package/lib/core/analytics/types.d.ts +48 -0
- package/lib/core/analytics/types.js +3 -0
- package/lib/core/analytics/user-identity.d.ts +41 -0
- package/lib/core/analytics/user-identity.js +141 -0
- package/lib/core/analytics/version.d.ts +6 -0
- package/lib/core/analytics/version.js +10 -0
- package/lib/core/attribution.d.ts +111 -0
- package/lib/core/attribution.js +142 -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 +31 -0
- package/lib/core/base.class.d.ts +152 -0
- package/lib/core/base.class.js +172 -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 +133 -0
- package/lib/core/constants/core.js +209 -0
- package/lib/core/constants/swap-router.d.ts +150 -0
- package/lib/core/constants/swap-router.js +169 -0
- package/lib/core/constants/vaults.d.ts +93 -0
- package/lib/core/constants/vaults.js +273 -0
- package/lib/core/constants/web3.d.ts +91 -0
- package/lib/core/constants/web3.js +229 -0
- package/lib/core/errors/index.d.ts +114 -0
- package/lib/core/errors/index.js +183 -0
- package/lib/core/fetcher.d.ts +198 -0
- package/lib/core/fetcher.js +903 -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 +682 -0
- package/lib/core/helpers/chain-support.d.ts +80 -0
- package/lib/core/helpers/chain-support.js +115 -0
- package/lib/core/helpers/core.d.ts +68 -0
- package/lib/core/helpers/core.js +285 -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 +52 -0
- package/lib/core/helpers/signer.js +145 -0
- package/lib/core/helpers/swap-router.d.ts +211 -0
- package/lib/core/helpers/swap-router.js +480 -0
- package/lib/core/helpers/vault-version.d.ts +23 -0
- package/lib/core/helpers/vault-version.js +75 -0
- package/lib/core/helpers/vaults.d.ts +89 -0
- package/lib/core/helpers/vaults.js +235 -0
- package/lib/core/helpers/web3.d.ts +353 -0
- package/lib/core/helpers/web3.js +992 -0
- package/lib/core/index.d.ts +23 -0
- package/lib/core/index.js +40 -0
- package/lib/core/logger/index.d.ts +98 -0
- package/lib/core/logger/index.js +144 -0
- package/lib/core/logger/slack.d.ts +16 -0
- package/lib/core/logger/slack.js +57 -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 +128 -0
- package/lib/evm/methods/crossChainVault.js +853 -0
- package/lib/evm/methods/crossChainVaultRegistry.d.ts +93 -0
- package/lib/evm/methods/crossChainVaultRegistry.js +240 -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 +527 -0
- package/lib/main.js +601 -0
- package/lib/modules/api/fetcher.d.ts +82 -0
- package/lib/modules/api/fetcher.js +150 -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 +313 -0
- package/lib/modules/api/main.js +479 -0
- package/lib/modules/sub-accounts/fetcher.d.ts +53 -0
- package/lib/modules/sub-accounts/fetcher.js +120 -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 +243 -0
- package/lib/modules/sub-accounts/main.js +205 -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 +64 -0
- package/lib/modules/vaults/adapter.helpers.js +184 -0
- package/lib/modules/vaults/fetcher.d.ts +147 -0
- package/lib/modules/vaults/fetcher.js +368 -0
- package/lib/modules/vaults/getters.d.ts +570 -0
- package/lib/modules/vaults/getters.js +3051 -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 +601 -0
- package/lib/modules/vaults/main.js +1623 -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 +225 -0
- package/lib/modules/vaults/read.actions.js +596 -0
- package/lib/modules/vaults/types.d.ts +71 -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 +140 -0
- package/lib/modules/vaults/utils.js +799 -0
- package/lib/modules/vaults/write.actions.d.ts +529 -0
- package/lib/modules/vaults/write.actions.js +1749 -0
- package/lib/polyfills.d.ts +1 -0
- package/lib/polyfills.js +12 -0
- package/lib/sdk.d.ts +26721 -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 +38 -0
- package/lib/services/debank/utils.js +297 -0
- package/lib/services/layerzero/deposits.d.ts +49 -0
- package/lib/services/layerzero/deposits.js +166 -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 +9 -0
- package/lib/services/octavfi/fetcher.js +103 -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 +212 -0
- package/lib/services/subgraph/fetcher.d.ts +2 -0
- package/lib/services/subgraph/fetcher.js +61 -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 +45 -0
- package/lib/services/subgraph/schema.js +75 -0
- package/lib/services/subgraph/vaults.d.ts +25 -0
- package/lib/services/subgraph/vaults.js +1106 -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/types/api.d.ts +280 -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 +140 -0
- package/lib/types/sub-accounts.js +3 -0
- package/lib/types/subgraph.d.ts +74 -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 +714 -0
- package/lib/types/vaults.js +24 -0
- package/lib/types/web3.d.ts +51 -0
- package/lib/types/web3.js +14 -0
- package/lib/types/webserver.d.ts +698 -0
- package/lib/types/webserver.js +3 -0
- package/package.json +78 -0
|
@@ -0,0 +1,379 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.describeSolanaError = describeSolanaError;
|
|
4
|
+
exports.handleSolanaDeposit = handleSolanaDeposit;
|
|
5
|
+
exports.handleSolanaRedeem = handleSolanaRedeem;
|
|
6
|
+
const anchor_1 = require("@coral-xyz/anchor");
|
|
7
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
8
|
+
const spl_token_1 = require("@solana/spl-token");
|
|
9
|
+
const constants_1 = require("./constants");
|
|
10
|
+
const utils_1 = require("./utils");
|
|
11
|
+
const core_1 = require("../../core");
|
|
12
|
+
/**
|
|
13
|
+
* User-facing fallback for a throwable that carries no extractable reason.
|
|
14
|
+
* Surfaces as e.g. `"Solana deposit failed: please try again"` — actionable,
|
|
15
|
+
* and without telling the user we couldn't classify the failure.
|
|
16
|
+
*/
|
|
17
|
+
const REASONLESS_SOLANA_ERROR = 'please try again';
|
|
18
|
+
/**
|
|
19
|
+
* Extract a human- and machine-readable reason from a thrown Solana/Anchor
|
|
20
|
+
* error.
|
|
21
|
+
*
|
|
22
|
+
* Anchor's {@link https://github.com/coral-xyz/anchor `ProgramError`} calls
|
|
23
|
+
* `super()` with no argument, so its `.message` is the empty string by
|
|
24
|
+
* construction — the real reason lives on `.msg`/`.code` (and `.toString()`).
|
|
25
|
+
* `AnchorError` puts it on `.error.errorMessage` / `.error.errorCode.number`.
|
|
26
|
+
* Reading `.message` directly (as this file used to) therefore rendered
|
|
27
|
+
* `"Solana deposit failed: "` for every recognized on-chain revert — dropping
|
|
28
|
+
* the numeric code the team needs to tell "Vault is paused" from
|
|
29
|
+
* "Insufficient amount" from an account-constraint violation.
|
|
30
|
+
*
|
|
31
|
+
* When no reason can be extracted, returns an actionable, user-facing fallback
|
|
32
|
+
* rather than an "unknown error" admission — the raw throwable is still
|
|
33
|
+
* preserved on the wrapped error's `cause` and in telemetry for diagnosis.
|
|
34
|
+
*/
|
|
35
|
+
function describeSolanaError(e) {
|
|
36
|
+
if (!(e instanceof Error))
|
|
37
|
+
return REASONLESS_SOLANA_ERROR;
|
|
38
|
+
const anchor = e;
|
|
39
|
+
const reason = anchor.error?.errorMessage ?? anchor.msg ?? '';
|
|
40
|
+
const code = anchor.error?.errorCode?.number ?? anchor.code;
|
|
41
|
+
if (reason)
|
|
42
|
+
return code === undefined ? reason : `${reason} (code ${code})`;
|
|
43
|
+
// SendTransactionError / generic Error carry a non-empty `.message`.
|
|
44
|
+
if (e.message)
|
|
45
|
+
return e.message;
|
|
46
|
+
// Last resort: a subclass may override `toString()` (never the empty string).
|
|
47
|
+
const str = e.toString();
|
|
48
|
+
return str && str !== e.name && str !== `${e.name}: `
|
|
49
|
+
? str
|
|
50
|
+
: REASONLESS_SOLANA_ERROR;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Deposit funds into a Solana August vault and mint share tokens.
|
|
54
|
+
*
|
|
55
|
+
* @param depositAmount `bigint` is treated as raw on-chain units (preferred
|
|
56
|
+
* — no JS-float round-trip). `number` is treated as a UI amount and
|
|
57
|
+
* scaled by the deposit mint's decimals via {@link uiAmountToRawBn}.
|
|
58
|
+
* @throws AugustValidationError on missing wallet/programId or invalid amount.
|
|
59
|
+
* @remarks The on-chain `deposit` instruction has no `min_shares_out`
|
|
60
|
+
* parameter; slippage cannot be enforced on-chain until the program ships
|
|
61
|
+
* that argument.
|
|
62
|
+
*/
|
|
63
|
+
async function handleSolanaDeposit({ provider, connection, network = constants_1.fallbackNetwork, vaultProgramId, vaultAddress, depositAmount, publicKey, sendTransaction, idl, }) {
|
|
64
|
+
try {
|
|
65
|
+
if (!publicKey)
|
|
66
|
+
throw new core_1.AugustValidationError('INVALID_INPUT', 'handleSolanaDeposit: wallet not connected');
|
|
67
|
+
if (depositAmount === undefined ||
|
|
68
|
+
depositAmount === null ||
|
|
69
|
+
(typeof depositAmount === 'bigint' && depositAmount <= 0n) ||
|
|
70
|
+
(typeof depositAmount === 'number' && !(depositAmount > 0)))
|
|
71
|
+
throw new core_1.AugustValidationError('INVALID_INPUT', 'handleSolanaDeposit: depositAmount is required and must be > 0');
|
|
72
|
+
if (!vaultProgramId)
|
|
73
|
+
throw new core_1.AugustValidationError('INVALID_INPUT', 'handleSolanaDeposit: vaultProgramId is required');
|
|
74
|
+
const { depositMint, shareMint, vaultVersion } = await utils_1.SolanaUtils.getVaultMints({
|
|
75
|
+
network,
|
|
76
|
+
connection,
|
|
77
|
+
vaultProgramId,
|
|
78
|
+
vaultAddress,
|
|
79
|
+
idl,
|
|
80
|
+
});
|
|
81
|
+
if (!depositMint || !shareMint) {
|
|
82
|
+
throw new Error('Failed to read vault mints from on-chain state');
|
|
83
|
+
}
|
|
84
|
+
const _vaultProgramId = new web3_js_1.PublicKey(vaultProgramId);
|
|
85
|
+
const _publicKey = new web3_js_1.PublicKey(publicKey);
|
|
86
|
+
const _depositMint = new web3_js_1.PublicKey(depositMint);
|
|
87
|
+
const program = utils_1.SolanaUtils.getProgram({
|
|
88
|
+
provider,
|
|
89
|
+
idl,
|
|
90
|
+
programId: _vaultProgramId.toBase58(),
|
|
91
|
+
});
|
|
92
|
+
core_1.Logger.log.info('handleSolanaDeposit', 'Program', program);
|
|
93
|
+
const vaultStatePda = vaultAddress
|
|
94
|
+
? new web3_js_1.PublicKey(vaultAddress)
|
|
95
|
+
: utils_1.SolanaUtils.deriveVaultStatePda(_vaultProgramId);
|
|
96
|
+
core_1.Logger.log.info('handleSolanaDeposit', 'Vault state PDA', vaultStatePda.toBase58());
|
|
97
|
+
const vaultTokenAtaPda = utils_1.SolanaUtils.deriveVaultTokenAtaPda(_vaultProgramId, _depositMint, vaultVersion);
|
|
98
|
+
core_1.Logger.log.info('handleSolanaDeposit', 'Vault token ATA PDA', vaultTokenAtaPda.toBase58());
|
|
99
|
+
// Use on-chain share mint from vault state instead of deriving a PDA,
|
|
100
|
+
// since PDA derivation assumes one share mint per program (single-vault only).
|
|
101
|
+
const shareMintAddr = new web3_js_1.PublicKey(shareMint);
|
|
102
|
+
core_1.Logger.log.info('handleSolanaDeposit', 'Share mint', shareMintAddr.toBase58());
|
|
103
|
+
// Get mint info to handle decimals
|
|
104
|
+
const mintInfo = await connection.getParsedAccountInfo(_depositMint);
|
|
105
|
+
if (!mintInfo.value) {
|
|
106
|
+
throw new Error('Could not fetch mint info');
|
|
107
|
+
}
|
|
108
|
+
const { decimals } = mintInfo.value.data.parsed.info;
|
|
109
|
+
let depositAmountRaw;
|
|
110
|
+
if (typeof depositAmount === 'bigint') {
|
|
111
|
+
depositAmountRaw = new anchor_1.BN(depositAmount.toString());
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
if (isNaN(depositAmount)) {
|
|
115
|
+
throw new core_1.AugustValidationError('INVALID_INPUT', 'Please enter a valid number for the deposit amount');
|
|
116
|
+
}
|
|
117
|
+
if (depositAmount <= 0) {
|
|
118
|
+
throw new core_1.AugustValidationError('INVALID_INPUT', 'Deposit amount must be greater than 0');
|
|
119
|
+
}
|
|
120
|
+
depositAmountRaw = (0, utils_1.uiAmountToRawBn)(depositAmount, decimals);
|
|
121
|
+
}
|
|
122
|
+
// Find user's token accounts
|
|
123
|
+
const userTokenAccounts = await connection.getParsedTokenAccountsByOwner(_publicKey, {
|
|
124
|
+
mint: _depositMint,
|
|
125
|
+
});
|
|
126
|
+
core_1.Logger.log.info('handleSolanaDeposit', 'User token accounts', userTokenAccounts);
|
|
127
|
+
const userShareAccounts = await connection.getParsedTokenAccountsByOwner(_publicKey, {
|
|
128
|
+
mint: shareMintAddr,
|
|
129
|
+
});
|
|
130
|
+
core_1.Logger.log.info('handleSolanaDeposit', 'User share accounts', userShareAccounts);
|
|
131
|
+
if (userTokenAccounts.value.length === 0) {
|
|
132
|
+
throw new core_1.AugustValidationError('INVALID_INPUT', 'No token account found for deposit mint. Please create a token account first.');
|
|
133
|
+
}
|
|
134
|
+
let senderShareAccount;
|
|
135
|
+
if (userShareAccounts.value.length === 0) {
|
|
136
|
+
core_1.Logger.log.info('handleSolanaDeposit', 'Creating share account');
|
|
137
|
+
// Create share account if it doesn't exist
|
|
138
|
+
senderShareAccount = await (0, spl_token_1.getAssociatedTokenAddress)(shareMintAddr, _publicKey);
|
|
139
|
+
core_1.Logger.log.info('handleSolanaDeposit', 'Sender share account', senderShareAccount.toBase58());
|
|
140
|
+
// Create the associated token account
|
|
141
|
+
const createAtaIx = (0, spl_token_1.createAssociatedTokenAccountInstruction)(_publicKey, // payer
|
|
142
|
+
senderShareAccount, // associated token account
|
|
143
|
+
_publicKey, // owner
|
|
144
|
+
shareMintAddr);
|
|
145
|
+
core_1.Logger.log.info('handleSolanaDeposit', 'Create ATA Ix', createAtaIx.programId.toBase58());
|
|
146
|
+
const transaction = new web3_js_1.Transaction().add(createAtaIx);
|
|
147
|
+
const signature = await sendTransaction(transaction, connection);
|
|
148
|
+
core_1.Logger.log.info('handleSolanaDeposit', 'Created share account:', signature.toString());
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
senderShareAccount = userShareAccounts.value[0]?.pubkey;
|
|
152
|
+
}
|
|
153
|
+
const senderTokenAccount = userTokenAccounts.value[0]?.pubkey;
|
|
154
|
+
core_1.Logger.log.info('handleSolanaDeposit', 'Sender token account', senderTokenAccount);
|
|
155
|
+
core_1.Logger.log.info('handleSolanaDeposit', '\n\nDeposit TX Params:\n');
|
|
156
|
+
core_1.Logger.log.info('handleSolanaDeposit', 'Program', depositAmountRaw);
|
|
157
|
+
core_1.Logger.log.info('handleSolanaDeposit', 'Vault state PDA', vaultStatePda.toBase58());
|
|
158
|
+
core_1.Logger.log.info('handleSolanaDeposit', 'Vault token ATA PDA', vaultTokenAtaPda.toBase58());
|
|
159
|
+
core_1.Logger.log.info('handleSolanaDeposit', 'Sender token account', senderTokenAccount?.toBase58());
|
|
160
|
+
core_1.Logger.log.info('handleSolanaDeposit', 'Sender share account', senderShareAccount?.toBase58());
|
|
161
|
+
core_1.Logger.log.info('handleSolanaDeposit', 'Share mint', shareMintAddr.toBase58());
|
|
162
|
+
core_1.Logger.log.info('handleSolanaDeposit', 'Deposit mint', _depositMint?.toBase58());
|
|
163
|
+
core_1.Logger.log.info('handleSolanaDeposit', 'Signer', _publicKey.toBase58());
|
|
164
|
+
// Get a fresh blockhash to avoid "Blockhash not found" errors
|
|
165
|
+
const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash('confirmed');
|
|
166
|
+
// TODO(slippage): pass `min_shares_out` here when the program ships it.
|
|
167
|
+
const tx = await program.methods
|
|
168
|
+
.deposit(depositAmountRaw)
|
|
169
|
+
.accounts({
|
|
170
|
+
vaultState: vaultStatePda,
|
|
171
|
+
vaultTokenAta: vaultTokenAtaPda,
|
|
172
|
+
senderTokenAccount,
|
|
173
|
+
senderShareAccount,
|
|
174
|
+
shareMint: shareMintAddr,
|
|
175
|
+
depositMint: depositMint,
|
|
176
|
+
signer: publicKey,
|
|
177
|
+
tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
|
|
178
|
+
})
|
|
179
|
+
.rpc({
|
|
180
|
+
skipPreflight: false,
|
|
181
|
+
preflightCommitment: 'confirmed',
|
|
182
|
+
});
|
|
183
|
+
core_1.Logger.log.info('handleSolanaDeposit', 'Deposit successful:', tx);
|
|
184
|
+
// Wait for confirmation with the blockhash we used
|
|
185
|
+
await connection.confirmTransaction({
|
|
186
|
+
signature: tx,
|
|
187
|
+
blockhash,
|
|
188
|
+
lastValidBlockHeight,
|
|
189
|
+
}, 'confirmed');
|
|
190
|
+
return tx;
|
|
191
|
+
}
|
|
192
|
+
catch (e) {
|
|
193
|
+
if (e instanceof core_1.AugustSDKError)
|
|
194
|
+
throw e;
|
|
195
|
+
const depositAmountForLog = typeof depositAmount === 'bigint'
|
|
196
|
+
? depositAmount.toString()
|
|
197
|
+
: depositAmount;
|
|
198
|
+
core_1.Logger.log.error('handleSolanaDeposit', e, {
|
|
199
|
+
vaultProgramId: String(vaultProgramId),
|
|
200
|
+
vaultAddress: vaultAddress ? String(vaultAddress) : undefined,
|
|
201
|
+
depositAmount: depositAmountForLog,
|
|
202
|
+
});
|
|
203
|
+
throw new core_1.AugustSDKError('UNKNOWN', `Solana deposit failed: ${describeSolanaError(e)}`, {
|
|
204
|
+
cause: e,
|
|
205
|
+
context: {
|
|
206
|
+
vaultProgramId: String(vaultProgramId),
|
|
207
|
+
vaultAddress: vaultAddress ? String(vaultAddress) : undefined,
|
|
208
|
+
depositAmount: depositAmountForLog,
|
|
209
|
+
},
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Redeem vault shares back into the underlying mint on a Solana August vault.
|
|
215
|
+
*
|
|
216
|
+
* @param redeemShares `bigint` is treated as raw share-token units;
|
|
217
|
+
* `number` is treated as a UI amount. See {@link handleSolanaDeposit} for
|
|
218
|
+
* the same caveat about the missing on-chain slippage guard.
|
|
219
|
+
* @throws AugustValidationError on missing wallet/programId or invalid amount.
|
|
220
|
+
*/
|
|
221
|
+
async function handleSolanaRedeem({ provider, connection, vaultProgramId, vaultAddress, publicKey, redeemShares, sendTransaction, idl, }) {
|
|
222
|
+
try {
|
|
223
|
+
if (!publicKey)
|
|
224
|
+
throw new core_1.AugustValidationError('INVALID_INPUT', 'handleSolanaRedeem: wallet not connected');
|
|
225
|
+
if (redeemShares === undefined ||
|
|
226
|
+
redeemShares === null ||
|
|
227
|
+
(typeof redeemShares === 'bigint' && redeemShares <= 0n) ||
|
|
228
|
+
(typeof redeemShares === 'number' && !(redeemShares > 0)))
|
|
229
|
+
throw new core_1.AugustValidationError('INVALID_INPUT', 'handleSolanaRedeem: redeemShares is required and must be > 0');
|
|
230
|
+
if (!vaultProgramId)
|
|
231
|
+
throw new core_1.AugustValidationError('INVALID_INPUT', 'handleSolanaRedeem: vaultProgramId is required');
|
|
232
|
+
const { depositMint, shareMint, vaultVersion } = await utils_1.SolanaUtils.getVaultMints({
|
|
233
|
+
network: provider.connection.rpcEndpoint.includes('devnet')
|
|
234
|
+
? 'devnet'
|
|
235
|
+
: 'mainnet-beta',
|
|
236
|
+
connection,
|
|
237
|
+
vaultProgramId,
|
|
238
|
+
vaultAddress,
|
|
239
|
+
idl,
|
|
240
|
+
});
|
|
241
|
+
if (!depositMint || !shareMint) {
|
|
242
|
+
throw new Error('Failed to read vault mints from on-chain state');
|
|
243
|
+
}
|
|
244
|
+
const _vaultProgramId = new web3_js_1.PublicKey(vaultProgramId);
|
|
245
|
+
const _depositMint = new web3_js_1.PublicKey(depositMint);
|
|
246
|
+
const _publicKey = new web3_js_1.PublicKey(publicKey);
|
|
247
|
+
const program = utils_1.SolanaUtils.getProgram({
|
|
248
|
+
provider,
|
|
249
|
+
idl,
|
|
250
|
+
programId: _vaultProgramId.toBase58(),
|
|
251
|
+
});
|
|
252
|
+
const vaultStatePda = vaultAddress
|
|
253
|
+
? new web3_js_1.PublicKey(vaultAddress)
|
|
254
|
+
: utils_1.SolanaUtils.deriveVaultStatePda(_vaultProgramId);
|
|
255
|
+
const vaultTokenAtaPda = utils_1.SolanaUtils.deriveVaultTokenAtaPda(_vaultProgramId, _depositMint, vaultVersion);
|
|
256
|
+
// Use on-chain share mint from vault state instead of deriving a PDA,
|
|
257
|
+
// since PDA derivation assumes one share mint per program (single-vault only).
|
|
258
|
+
const shareMintAddr = new web3_js_1.PublicKey(shareMint);
|
|
259
|
+
// Get share mint info to handle decimals
|
|
260
|
+
const shareMintInfo = await connection.getParsedAccountInfo(shareMintAddr);
|
|
261
|
+
if (!shareMintInfo.value) {
|
|
262
|
+
throw new Error('Could not fetch share mint info');
|
|
263
|
+
}
|
|
264
|
+
const shareDecimals = shareMintInfo.value.data.parsed.info
|
|
265
|
+
.decimals;
|
|
266
|
+
let redeemSharesRaw;
|
|
267
|
+
if (typeof redeemShares === 'bigint') {
|
|
268
|
+
redeemSharesRaw = new anchor_1.BN(redeemShares.toString());
|
|
269
|
+
}
|
|
270
|
+
else {
|
|
271
|
+
if (isNaN(redeemShares)) {
|
|
272
|
+
throw new core_1.AugustValidationError('INVALID_INPUT', 'Please enter a valid number for the shares to redeem');
|
|
273
|
+
}
|
|
274
|
+
if (redeemShares <= 0) {
|
|
275
|
+
throw new core_1.AugustValidationError('INVALID_INPUT', 'Shares to redeem must be greater than 0');
|
|
276
|
+
}
|
|
277
|
+
redeemSharesRaw = (0, utils_1.uiAmountToRawBn)(redeemShares, shareDecimals);
|
|
278
|
+
}
|
|
279
|
+
// Find user's token accounts
|
|
280
|
+
const userTokenAccounts = await connection.getParsedTokenAccountsByOwner(_publicKey, {
|
|
281
|
+
mint: _depositMint,
|
|
282
|
+
});
|
|
283
|
+
const userShareAccounts = await connection.getParsedTokenAccountsByOwner(_publicKey, {
|
|
284
|
+
mint: shareMintAddr,
|
|
285
|
+
});
|
|
286
|
+
if (userTokenAccounts.value.length === 0) {
|
|
287
|
+
throw new core_1.AugustValidationError('INVALID_INPUT', 'No token account found for deposit mint. Please create a token account first.');
|
|
288
|
+
}
|
|
289
|
+
if (userShareAccounts.value.length === 0) {
|
|
290
|
+
throw new core_1.AugustValidationError('INVALID_INPUT', 'No share account found. You need to deposit first to get shares before you can redeem.');
|
|
291
|
+
}
|
|
292
|
+
const senderTokenAccount = userTokenAccounts?.value[0]?.pubkey;
|
|
293
|
+
const senderShareAccount = userShareAccounts?.value[0]?.pubkey;
|
|
294
|
+
// Get the fee recipient from vault state
|
|
295
|
+
const readOnlyProvider = utils_1.SolanaUtils.getReadOnlyProvider({ connection });
|
|
296
|
+
const readOnlyProgram = utils_1.SolanaUtils.getProgram({
|
|
297
|
+
provider: readOnlyProvider,
|
|
298
|
+
idl,
|
|
299
|
+
programId: _vaultProgramId.toBase58(),
|
|
300
|
+
});
|
|
301
|
+
const vaultStateData = await readOnlyProgram.account.vaultState.fetch(vaultStatePda);
|
|
302
|
+
// Get the fee recipient's token account
|
|
303
|
+
const feeRecipientTokenAccount = await (0, spl_token_1.getAssociatedTokenAddress)(_depositMint, vaultStateData.feeRecipient);
|
|
304
|
+
// Check if the fee recipient token account exists, if not create it
|
|
305
|
+
const feeRecipientAccountInfo = await connection.getAccountInfo(feeRecipientTokenAccount);
|
|
306
|
+
if (!feeRecipientAccountInfo) {
|
|
307
|
+
const createFeeRecipientAtaIx = (0, spl_token_1.createAssociatedTokenAccountInstruction)(_publicKey, // payer (user pays for the account creation)
|
|
308
|
+
feeRecipientTokenAccount, // associated token account
|
|
309
|
+
vaultStateData.feeRecipient, // owner (the actual fee recipient)
|
|
310
|
+
_depositMint);
|
|
311
|
+
const createAccountTx = new web3_js_1.Transaction().add(createFeeRecipientAtaIx);
|
|
312
|
+
const createAccountSignature = await sendTransaction(createAccountTx, connection);
|
|
313
|
+
core_1.Logger.log.info('handleSolanaRedeem', 'Fee recipient token account created:', createAccountSignature);
|
|
314
|
+
// Wait a moment for the account to be created
|
|
315
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
316
|
+
}
|
|
317
|
+
else {
|
|
318
|
+
core_1.Logger.log.info('handleSolanaRedeem', 'Fee recipient token account already exists');
|
|
319
|
+
}
|
|
320
|
+
core_1.Logger.log.info('handleSolanaRedeem', '\n\nRedeem TX Params:\n');
|
|
321
|
+
core_1.Logger.log.info('handleSolanaRedeem', 'Redeem shares (UI):', redeemShares);
|
|
322
|
+
core_1.Logger.log.info('handleSolanaRedeem', 'Redeem shares (raw):', redeemSharesRaw);
|
|
323
|
+
core_1.Logger.log.info('handleSolanaRedeem', 'Share decimals:', shareDecimals);
|
|
324
|
+
core_1.Logger.log.info('handleSolanaRedeem', 'Vault state PDA:', vaultStatePda.toBase58());
|
|
325
|
+
core_1.Logger.log.info('handleSolanaRedeem', 'Vault token ATA PDA:', vaultTokenAtaPda.toBase58());
|
|
326
|
+
core_1.Logger.log.info('handleSolanaRedeem', 'Sender token account:', senderTokenAccount?.toBase58());
|
|
327
|
+
core_1.Logger.log.info('handleSolanaRedeem', 'Sender share account:', senderShareAccount?.toBase58());
|
|
328
|
+
core_1.Logger.log.info('handleSolanaRedeem', 'Fee recipient account:', feeRecipientTokenAccount.toBase58());
|
|
329
|
+
core_1.Logger.log.info('handleSolanaRedeem', 'Share mint:', shareMintAddr.toBase58());
|
|
330
|
+
core_1.Logger.log.info('handleSolanaRedeem', 'Deposit mint:', _depositMint?.toBase58());
|
|
331
|
+
core_1.Logger.log.info('handleSolanaRedeem', 'Signer:', _publicKey.toBase58());
|
|
332
|
+
// Get a fresh blockhash to avoid "Blockhash not found" errors
|
|
333
|
+
const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash('confirmed');
|
|
334
|
+
const tx = await program.methods
|
|
335
|
+
.redeem(redeemSharesRaw)
|
|
336
|
+
.accounts({
|
|
337
|
+
vaultState: vaultStatePda,
|
|
338
|
+
vaultDepositAta: vaultTokenAtaPda,
|
|
339
|
+
senderTokenAccount,
|
|
340
|
+
senderShareAccount,
|
|
341
|
+
feeRecipientAccount: feeRecipientTokenAccount, // The actual fee recipient's token account
|
|
342
|
+
shareMint: shareMintAddr,
|
|
343
|
+
depositMint: _depositMint,
|
|
344
|
+
signer: _publicKey,
|
|
345
|
+
tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
|
|
346
|
+
})
|
|
347
|
+
.rpc({
|
|
348
|
+
skipPreflight: false,
|
|
349
|
+
preflightCommitment: 'confirmed',
|
|
350
|
+
});
|
|
351
|
+
core_1.Logger.log.info('handleSolanaRedeem', 'Redeem successful:', tx);
|
|
352
|
+
// Wait for confirmation with the blockhash we used
|
|
353
|
+
await connection.confirmTransaction({
|
|
354
|
+
signature: tx,
|
|
355
|
+
blockhash,
|
|
356
|
+
lastValidBlockHeight,
|
|
357
|
+
}, 'confirmed');
|
|
358
|
+
return tx;
|
|
359
|
+
}
|
|
360
|
+
catch (e) {
|
|
361
|
+
if (e instanceof core_1.AugustSDKError)
|
|
362
|
+
throw e;
|
|
363
|
+
const redeemSharesForLog = typeof redeemShares === 'bigint' ? redeemShares.toString() : redeemShares;
|
|
364
|
+
core_1.Logger.log.error('handleSolanaRedeem', e, {
|
|
365
|
+
vaultProgramId: String(vaultProgramId),
|
|
366
|
+
vaultAddress: vaultAddress ? String(vaultAddress) : undefined,
|
|
367
|
+
redeemShares: redeemSharesForLog,
|
|
368
|
+
});
|
|
369
|
+
throw new core_1.AugustSDKError('UNKNOWN', `Solana redeem failed: ${describeSolanaError(e)}`, {
|
|
370
|
+
cause: e,
|
|
371
|
+
context: {
|
|
372
|
+
vaultProgramId: String(vaultProgramId),
|
|
373
|
+
vaultAddress: vaultAddress ? String(vaultAddress) : undefined,
|
|
374
|
+
redeemShares: redeemSharesForLog,
|
|
375
|
+
},
|
|
376
|
+
});
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
//# sourceMappingURL=vault.actions.js.map
|
|
@@ -0,0 +1,28 @@
|
|
|
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
|
+
* @returns Base64-encoded XDR ready for wallet signing; pass the signed
|
|
26
|
+
* XDR to {@link submitStellarTransaction}.
|
|
27
|
+
*/
|
|
28
|
+
export declare function handleStellarRedeem(params: IStellarRedeemParams): Promise<string>;
|
|
@@ -0,0 +1,77 @@
|
|
|
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
|
+
function validateContractAddress(contractId) {
|
|
16
|
+
if (!(0, utils_1.isStellarAddress)(contractId) || contractId[0] !== 'C') {
|
|
17
|
+
throw new core_1.AugustValidationError('INVALID_ADDRESS', `Invalid contract address: expected a Stellar contract (C-prefix), got "${contractId}"`);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function validateAccountAddress(address, label) {
|
|
21
|
+
if (!(0, utils_1.isStellarAddress)(address) || address[0] !== 'G') {
|
|
22
|
+
throw new core_1.AugustValidationError('INVALID_ADDRESS', `Invalid ${label} address: expected a Stellar account (G-prefix), got "${address}"`);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Build a self-operation Soroban transaction where all address roles
|
|
27
|
+
* (receiver, from/owner, operator) are set to the same user address.
|
|
28
|
+
*
|
|
29
|
+
* Note: This only supports self-operations. If delegated operations
|
|
30
|
+
* (distinct receiver/owner/operator) are needed in the future,
|
|
31
|
+
* a separate argument builder will be required.
|
|
32
|
+
*/
|
|
33
|
+
function buildSelfOperationArgs(amount, userAddress) {
|
|
34
|
+
const userScVal = new stellar_sdk_1.Address(userAddress).toScVal();
|
|
35
|
+
return [
|
|
36
|
+
(0, stellar_sdk_1.nativeToScVal)(amount, { type: 'i128' }),
|
|
37
|
+
userScVal,
|
|
38
|
+
userScVal,
|
|
39
|
+
userScVal,
|
|
40
|
+
];
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Deposit assets into a Stellar vault (self-deposit).
|
|
44
|
+
*
|
|
45
|
+
* Builds an unsigned Soroban transaction invoking the vault's `deposit` function.
|
|
46
|
+
* All three address roles (receiver, from, operator) are set to senderAddress.
|
|
47
|
+
*
|
|
48
|
+
* Contract signature: deposit(assets: i128, receiver: Address, from: Address, operator: Address) -> i128
|
|
49
|
+
*
|
|
50
|
+
* @returns Base64-encoded XDR of the unsigned transaction, ready for wallet signing.
|
|
51
|
+
*/
|
|
52
|
+
async function handleStellarDeposit(params) {
|
|
53
|
+
const { contractId, amount, senderAddress, network, sorobanRpcUrl } = params;
|
|
54
|
+
validateContractAddress(contractId);
|
|
55
|
+
validateAccountAddress(senderAddress, 'sender');
|
|
56
|
+
const config = (0, soroban_1.resolveNetworkConfig)(network, sorobanRpcUrl);
|
|
57
|
+
const args = buildSelfOperationArgs((0, soroban_1.toBigIntAmount)(amount, 'deposit amount'), senderAddress);
|
|
58
|
+
return (0, soroban_1.buildSorobanTx)(config, senderAddress, contractId, 'deposit', args);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Build an unsigned self-redeem Soroban transaction (receiver, owner, and
|
|
62
|
+
* operator all = `receiverAddress`). Assumes the deployed vault exposes
|
|
63
|
+
* `redeem(shares: i128, receiver, owner, operator) -> i128`; divergence
|
|
64
|
+
* surfaces as a generic Soroban simulation error.
|
|
65
|
+
*
|
|
66
|
+
* @returns Base64-encoded XDR ready for wallet signing; pass the signed
|
|
67
|
+
* XDR to {@link submitStellarTransaction}.
|
|
68
|
+
*/
|
|
69
|
+
async function handleStellarRedeem(params) {
|
|
70
|
+
const { contractId, shares, receiverAddress, network, sorobanRpcUrl } = params;
|
|
71
|
+
validateContractAddress(contractId);
|
|
72
|
+
validateAccountAddress(receiverAddress, 'receiver');
|
|
73
|
+
const config = (0, soroban_1.resolveNetworkConfig)(network, sorobanRpcUrl);
|
|
74
|
+
const args = buildSelfOperationArgs((0, soroban_1.toBigIntAmount)(shares, 'redeem shares'), receiverAddress);
|
|
75
|
+
return (0, soroban_1.buildSorobanTx)(config, receiverAddress, contractId, 'redeem', args);
|
|
76
|
+
}
|
|
77
|
+
//# 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;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Stellar Constants
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.MAX_POLL_ATTEMPTS = exports.POLL_INTERVAL_BACKOFF = exports.POLL_INTERVAL_MAX_MS = exports.POLL_INTERVAL_MS = exports.MAX_FEE_STROOPS = exports.QUERY_TIMEOUT_SECONDS = exports.TX_TIMEOUT_SECONDS = exports.STELLAR_FALLBACK_DECIMALS = exports.NETWORK_PASSPHRASES = exports.SOROBAN_RPC_URLS = exports.STELLAR_CHAIN = exports.STELLAR_CHAIN_ID = void 0;
|
|
7
|
+
const stellar_sdk_1 = require("@stellar/stellar-sdk");
|
|
8
|
+
const web3_1 = require("../../core/constants/web3");
|
|
9
|
+
// Synthetic chain ID for Stellar, sourced from SPECIAL_CHAINS. See core/constants/web3.ts for all non-EVM chain IDs.
|
|
10
|
+
exports.STELLAR_CHAIN_ID = web3_1.SPECIAL_CHAINS.stellar.chainId;
|
|
11
|
+
exports.STELLAR_CHAIN = web3_1.SPECIAL_CHAINS.stellar;
|
|
12
|
+
exports.SOROBAN_RPC_URLS = {
|
|
13
|
+
mainnet: 'https://soroban-rpc.mainnet.stellar.gateway.fm',
|
|
14
|
+
testnet: 'https://soroban-testnet.stellar.org',
|
|
15
|
+
};
|
|
16
|
+
exports.NETWORK_PASSPHRASES = {
|
|
17
|
+
mainnet: stellar_sdk_1.Networks.PUBLIC,
|
|
18
|
+
testnet: stellar_sdk_1.Networks.TESTNET,
|
|
19
|
+
};
|
|
20
|
+
// Most Stellar/Soroban tokens use 7 decimal places (matching XLM's 10^7 stroops convention).
|
|
21
|
+
// Used as fallback when deposit_token_decimals is not available from backend metadata.
|
|
22
|
+
exports.STELLAR_FALLBACK_DECIMALS = 7;
|
|
23
|
+
/**
|
|
24
|
+
* Validity window for a submitted Soroban invocation (seconds).
|
|
25
|
+
*
|
|
26
|
+
* This becomes the transaction's `maxTime`. Validators reject a tx whose
|
|
27
|
+
* `maxTime` has passed (`txTOO_LATE`), so the window must outlast the slowest
|
|
28
|
+
* realistic sign-then-submit path: hardware wallets, careful manual review,
|
|
29
|
+
* and institutional approval flows (e.g. Fordefi) that don't sign instantly.
|
|
30
|
+
* 10 minutes comfortably covers those while staying well inside the Soroban
|
|
31
|
+
* footprint/ledger-entry TTL, so the simulated footprint can't go stale first.
|
|
32
|
+
*
|
|
33
|
+
* The window is anchored to the *network* clock (see `getNetworkCloseTime` in
|
|
34
|
+
* soroban.ts), not the signer's `Date.now()`, so a skewed device clock can't
|
|
35
|
+
* make the deadline expire early.
|
|
36
|
+
*/
|
|
37
|
+
exports.TX_TIMEOUT_SECONDS = 600;
|
|
38
|
+
/** Timeout for read-only Soroban simulation queries (seconds). */
|
|
39
|
+
exports.QUERY_TIMEOUT_SECONDS = 10;
|
|
40
|
+
/**
|
|
41
|
+
* Max fee ceiling in stroops (1_000_000 stroops = 0.1 XLM).
|
|
42
|
+
* assembleTransaction adjusts to the actual fee from simulation.
|
|
43
|
+
*/
|
|
44
|
+
exports.MAX_FEE_STROOPS = '1000000';
|
|
45
|
+
/** Initial confirmation-poll interval (ms). Grows up to {@link POLL_INTERVAL_MAX_MS}. */
|
|
46
|
+
exports.POLL_INTERVAL_MS = 2000;
|
|
47
|
+
/** Cap for the backed-off confirmation-poll interval (ms). */
|
|
48
|
+
exports.POLL_INTERVAL_MAX_MS = 8000;
|
|
49
|
+
/** Multiplier applied to the poll interval after each NOT_FOUND poll. */
|
|
50
|
+
exports.POLL_INTERVAL_BACKOFF = 1.5;
|
|
51
|
+
/** Maximum number of polling attempts before timeout. */
|
|
52
|
+
exports.MAX_POLL_ATTEMPTS = 30;
|
|
53
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stellar Vault Getters
|
|
3
|
+
*
|
|
4
|
+
* Data fetching for Stellar vaults. Enriches backend metadata with on-chain
|
|
5
|
+
* total assets, total supply, and share decimals from Soroban RPC. Also
|
|
6
|
+
* provides user position queries and deposit preview (convertToShares).
|
|
7
|
+
* Falls back to backend TVL for total assets, zero for total supply, and
|
|
8
|
+
* STELLAR_FALLBACK_DECIMALS for share decimals when on-chain queries fail.
|
|
9
|
+
*/
|
|
10
|
+
import type { ITokenizedVault, IVault } from '../../types';
|
|
11
|
+
import type { IVaultBaseOptions } from '../../modules/vaults/types';
|
|
12
|
+
import type { IStellarNetwork, IStellarUserPosition } from './types';
|
|
13
|
+
/**
|
|
14
|
+
* Build a unified IVault from backend + on-chain data for Stellar vaults.
|
|
15
|
+
* Reads total assets and total supply from the Soroban contract via RPC.
|
|
16
|
+
* Falls back to backend `latest_reported_tvl` for total assets, or zero
|
|
17
|
+
* for total supply, when on-chain queries fail.
|
|
18
|
+
*/
|
|
19
|
+
export declare const getStellarVault: (tokenizedVault: ITokenizedVault, options: IVaultBaseOptions) => Promise<IVault>;
|
|
20
|
+
/**
|
|
21
|
+
* Get user position for a Stellar vault.
|
|
22
|
+
* Queries the vault contract's balance(address) and decimals() functions via Soroban RPC.
|
|
23
|
+
*
|
|
24
|
+
* Returns `{ shares, decimals, decimalsFromFallback }` on success (shares may be
|
|
25
|
+
* '0' for zero balance), or null when the balance query fails. The two reads are
|
|
26
|
+
* independent: a `decimals()` failure does NOT null the result — instead
|
|
27
|
+
* `decimals` falls back to STELLAR_FALLBACK_DECIMALS (7) and
|
|
28
|
+
* `decimalsFromFallback` is set to `true` so callers can tell a fabricated 7
|
|
29
|
+
* apart from a genuine 7-decimal vault.
|
|
30
|
+
*
|
|
31
|
+
* Why this matters: an ERC4626 offset vault has share decimals = asset + offset
|
|
32
|
+
* (e.g. 13). A consumer that sizes a redeem trusting a silent fallback 7 would
|
|
33
|
+
* under-redeem by `10^offset`. Callers that settle a redeem from this position
|
|
34
|
+
* MUST refuse (surface an error) when `decimalsFromFallback` is `true` rather
|
|
35
|
+
* than trusting `decimals`. See AUGUST-6381 (follow-up to AUGUST-6380).
|
|
36
|
+
*
|
|
37
|
+
* @param vaultAddress - Stellar vault contract ID (C… address)
|
|
38
|
+
* @param walletAddress - User's Stellar account (G… address); validated upfront
|
|
39
|
+
* @param network - 'mainnet' | 'testnet' (defaults to 'mainnet')
|
|
40
|
+
* @param sorobanRpcUrl - Optional override Soroban RPC endpoint (e.g. a keyed
|
|
41
|
+
* Alchemy URL); becomes the primary with the SDK's public endpoints kept as
|
|
42
|
+
* failover. Omit to use the public endpoints.
|
|
43
|
+
* @returns The position, or `null` if the balance read failed or was unparseable.
|
|
44
|
+
* @throws AugustValidationError on an invalid `walletAddress`.
|
|
45
|
+
* @example
|
|
46
|
+
* ```ts
|
|
47
|
+
* const pos = await getStellarUserPosition(vault, wallet, 'mainnet');
|
|
48
|
+
* if (!pos || pos.decimalsFromFallback) {
|
|
49
|
+
* // Refuse to size a redeem — share scale is not authoritatively known.
|
|
50
|
+
* throw new Error('Stellar share decimals unresolved');
|
|
51
|
+
* }
|
|
52
|
+
* const human = Number(pos.shares) / 10 ** pos.decimals;
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
export declare const getStellarUserPosition: (vaultAddress: string, walletAddress: string, network?: IStellarNetwork, sorobanRpcUrl?: string) => Promise<IStellarUserPosition | null>;
|
|
56
|
+
/**
|
|
57
|
+
* Query the vault's `convert_to_shares` to preview how many shares a deposit
|
|
58
|
+
* amount would yield. Returns the raw share amount as a string, or null on
|
|
59
|
+
* failure.
|
|
60
|
+
*
|
|
61
|
+
* @param vaultAddress Stellar contract ID (C… address)
|
|
62
|
+
* @param rawAmount Deposit amount in the deposit token's smallest unit
|
|
63
|
+
* @param network 'mainnet' | 'testnet'
|
|
64
|
+
* @param sorobanRpcUrl - Optional override Soroban RPC endpoint (e.g. a keyed
|
|
65
|
+
* Alchemy URL); becomes the primary with the SDK's public endpoints kept as
|
|
66
|
+
* failover. Omit to use the public endpoints.
|
|
67
|
+
*/
|
|
68
|
+
export declare const convertToShares: (vaultAddress: string, rawAmount: string, network?: IStellarNetwork, sorobanRpcUrl?: string) => Promise<string | null>;
|