@augustdigital/sdk 8.3.1 → 8.5.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/lib/abis/ERC20_Bytes32.d.ts +4 -0
- package/lib/abis/ERC20_Bytes32.js +4 -0
- package/lib/abis/ERC4626.d.ts +1 -0
- package/lib/abis/ERC4626.js +1 -0
- package/lib/abis/ERC721.d.ts +1 -0
- package/lib/abis/ERC721.js +1 -0
- package/lib/abis/FeeOracle.js +1 -0
- package/lib/abis/LendingPool.js +1 -0
- package/lib/abis/LendingPoolV2.js +1 -0
- package/lib/abis/Multicall3.js +3 -0
- package/lib/abis/OFT.d.ts +20 -0
- package/lib/abis/OFT.js +20 -0
- package/lib/abis/SmartAccount.d.ts +1 -0
- package/lib/abis/SmartAccount.js +3 -0
- package/lib/abis/SwapRouter.d.ts +1 -0
- package/lib/abis/SwapRouter.js +1 -0
- package/lib/abis/UniversalSignatureValidator.js +3 -0
- package/lib/abis/index.d.ts +5 -0
- package/lib/abis/index.js +5 -0
- package/lib/adapters/evm/getters.d.ts +17 -2
- package/lib/adapters/evm/getters.js +35 -3
- package/lib/adapters/evm/index.d.ts +262 -0
- package/lib/adapters/evm/index.js +268 -1
- package/lib/adapters/evm/utils.d.ts +6 -0
- package/lib/adapters/evm/utils.js +7 -0
- package/lib/adapters/solana/constants.js +4 -1
- package/lib/adapters/solana/getters.d.ts +8 -0
- package/lib/adapters/solana/getters.js +21 -0
- package/lib/adapters/solana/idl/vault-idl.js +9 -0
- package/lib/adapters/solana/index.d.ts +55 -0
- package/lib/adapters/solana/index.js +57 -0
- package/lib/adapters/solana/utils.d.ts +28 -0
- package/lib/adapters/solana/utils.js +79 -4
- package/lib/adapters/solana/vault.actions.d.ts +19 -0
- package/lib/adapters/solana/vault.actions.js +47 -3
- package/lib/adapters/stellar/actions.d.ts +25 -0
- package/lib/adapters/stellar/actions.js +33 -0
- package/lib/adapters/stellar/constants.d.ts +26 -0
- package/lib/adapters/stellar/constants.js +29 -0
- package/lib/adapters/stellar/getters.d.ts +56 -0
- package/lib/adapters/stellar/getters.js +81 -0
- package/lib/adapters/stellar/index.d.ts +48 -0
- package/lib/adapters/stellar/index.js +48 -0
- package/lib/adapters/stellar/soroban.d.ts +20 -0
- package/lib/adapters/stellar/soroban.js +46 -0
- package/lib/adapters/stellar/submit.d.ts +12 -0
- package/lib/adapters/stellar/submit.js +19 -0
- package/lib/adapters/stellar/types.d.ts +27 -0
- package/lib/adapters/stellar/types.js +3 -0
- package/lib/adapters/stellar/utils.d.ts +10 -0
- package/lib/adapters/stellar/utils.js +10 -0
- package/lib/adapters/sui/getters.d.ts +6 -0
- package/lib/adapters/sui/getters.js +6 -0
- package/lib/adapters/sui/index.d.ts +15 -0
- package/lib/adapters/sui/index.js +15 -0
- package/lib/adapters/sui/transformer.d.ts +6 -0
- package/lib/adapters/sui/transformer.js +7 -0
- package/lib/adapters/sui/utils.d.ts +6 -0
- package/lib/adapters/sui/utils.js +6 -0
- package/lib/core/analytics/chain-name.d.ts +8 -0
- package/lib/core/analytics/chain-name.js +8 -0
- package/lib/core/analytics/constants.d.ts +4 -0
- package/lib/core/analytics/constants.js +4 -0
- package/lib/core/analytics/env.d.ts +25 -0
- package/lib/core/analytics/env.js +26 -0
- package/lib/core/analytics/index.d.ts +26 -0
- package/lib/core/analytics/index.js +35 -0
- package/lib/core/analytics/instrumentation.d.ts +26 -0
- package/lib/core/analytics/instrumentation.js +66 -2
- package/lib/core/analytics/method-taxonomy.d.ts +16 -0
- package/lib/core/analytics/method-taxonomy.js +18 -0
- package/lib/core/analytics/metrics.d.ts +23 -0
- package/lib/core/analytics/metrics.js +40 -0
- package/lib/core/analytics/sanitize.d.ts +38 -0
- package/lib/core/analytics/sanitize.js +46 -0
- package/lib/core/analytics/sentry-runtime.d.ts +11 -0
- package/lib/core/analytics/sentry-runtime.js +19 -0
- package/lib/core/analytics/sentry.d.ts +45 -0
- package/lib/core/analytics/sentry.js +115 -2
- package/lib/core/analytics/types.d.ts +27 -0
- package/lib/core/analytics/user-identity.d.ts +34 -0
- package/lib/core/analytics/user-identity.js +42 -0
- package/lib/core/analytics/version.d.ts +6 -1
- package/lib/core/analytics/version.js +6 -1
- package/lib/core/auth/verify.js +5 -0
- package/lib/core/base.class.d.ts +75 -0
- package/lib/core/base.class.js +56 -0
- package/lib/core/cache.d.ts +5 -0
- package/lib/core/cache.js +6 -0
- package/lib/core/constants/adapters.d.ts +15 -0
- package/lib/core/constants/adapters.js +28 -8
- package/lib/core/constants/core.d.ts +12 -1
- package/lib/core/constants/core.js +12 -0
- package/lib/core/constants/swap-router.d.ts +46 -0
- package/lib/core/constants/swap-router.js +50 -0
- package/lib/core/constants/vaults.d.ts +56 -0
- package/lib/core/constants/vaults.js +66 -1
- package/lib/core/constants/web3.d.ts +3 -0
- package/lib/core/constants/web3.js +18 -5
- package/lib/core/errors/index.d.ts +36 -0
- package/lib/core/errors/index.js +29 -0
- package/lib/core/fetcher.d.ts +134 -0
- package/lib/core/fetcher.js +191 -5
- package/lib/core/helpers/adapters.d.ts +9 -0
- package/lib/core/helpers/adapters.js +11 -0
- package/lib/core/helpers/chain-address.d.ts +10 -0
- package/lib/core/helpers/chain-address.js +11 -0
- package/lib/core/helpers/core.d.ts +42 -0
- package/lib/core/helpers/core.js +66 -1
- package/lib/core/helpers/explorer-link.d.ts +14 -0
- package/lib/core/helpers/explorer-link.js +14 -0
- package/lib/core/helpers/signer.d.ts +26 -0
- package/lib/core/helpers/signer.js +39 -0
- package/lib/core/helpers/swap-router.d.ts +32 -0
- package/lib/core/helpers/swap-router.js +32 -0
- package/lib/core/helpers/vault-version.d.ts +1 -0
- package/lib/core/helpers/vault-version.js +2 -0
- package/lib/core/helpers/vaults.d.ts +8 -0
- package/lib/core/helpers/vaults.js +22 -8
- package/lib/core/helpers/web3.d.ts +152 -0
- package/lib/core/helpers/web3.js +183 -6
- package/lib/core/logger/index.d.ts +55 -0
- package/lib/core/logger/index.js +19 -0
- package/lib/core/logger/slack.d.ts +3 -0
- package/lib/core/logger/slack.js +3 -0
- package/lib/core/vault-metadata.d.ts +6 -0
- package/lib/core/vault-metadata.js +6 -0
- package/lib/core/version-check.d.ts +52 -0
- package/lib/core/version-check.js +81 -0
- package/lib/evm/methods/crossChainVault.d.ts +90 -0
- package/lib/evm/methods/crossChainVault.js +186 -1
- package/lib/evm/methods/crossChainVaultRegistry.d.ts +93 -0
- package/lib/evm/methods/crossChainVaultRegistry.js +240 -0
- package/lib/evm/methods/index.d.ts +1 -0
- package/lib/evm/methods/index.js +1 -0
- package/lib/evm/types/crossChain.d.ts +202 -0
- package/lib/evm/types/crossChain.js +11 -0
- package/lib/index.d.ts +16 -0
- package/lib/index.js +19 -0
- package/lib/main.d.ts +288 -5
- package/lib/main.js +305 -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 +52 -0
- package/lib/modules/api/main.js +130 -0
- package/lib/modules/sub-accounts/fetcher.d.ts +15 -0
- package/lib/modules/sub-accounts/fetcher.js +15 -0
- package/lib/modules/sub-accounts/main.d.ts +33 -0
- package/lib/modules/sub-accounts/main.js +38 -0
- package/lib/modules/sub-accounts/utils.d.ts +3 -0
- package/lib/modules/sub-accounts/utils.js +3 -0
- package/lib/modules/vaults/adapter.helpers.d.ts +18 -0
- package/lib/modules/vaults/adapter.helpers.js +34 -0
- package/lib/modules/vaults/fetcher.d.ts +20 -0
- package/lib/modules/vaults/fetcher.js +40 -3
- package/lib/modules/vaults/getters.d.ts +295 -0
- package/lib/modules/vaults/getters.js +552 -12
- package/lib/modules/vaults/index.d.ts +12 -0
- package/lib/modules/vaults/index.js +12 -0
- package/lib/modules/vaults/main.d.ts +292 -4
- package/lib/modules/vaults/main.js +379 -7
- package/lib/modules/vaults/read.actions.d.ts +168 -0
- package/lib/modules/vaults/read.actions.js +143 -0
- package/lib/modules/vaults/types.d.ts +34 -0
- package/lib/modules/vaults/utils/call-data-decoder.d.ts +47 -0
- package/lib/modules/vaults/utils/call-data-decoder.js +56 -0
- package/lib/modules/vaults/utils/date-utils.d.ts +39 -0
- package/lib/modules/vaults/utils/date-utils.js +47 -1
- package/lib/modules/vaults/utils.d.ts +70 -0
- package/lib/modules/vaults/utils.js +108 -5
- package/lib/modules/vaults/write.actions.d.ts +363 -3
- package/lib/modules/vaults/write.actions.js +364 -2
- package/lib/polyfills.js +2 -0
- package/lib/sdk.d.ts +23705 -0
- package/lib/services/coingecko/fetcher.d.ts +13 -0
- package/lib/services/coingecko/fetcher.js +17 -0
- package/lib/services/debank/fetcher.d.ts +14 -0
- package/lib/services/debank/fetcher.js +12 -0
- package/lib/services/debank/utils.js +17 -0
- package/lib/services/layerzero/deposits.d.ts +11 -0
- package/lib/services/layerzero/deposits.js +34 -11
- package/lib/services/layerzero/redeems.d.ts +10 -0
- package/lib/services/layerzero/redeems.js +13 -0
- package/lib/services/layerzero/utils.d.ts +8 -0
- package/lib/services/layerzero/utils.js +11 -0
- package/lib/services/octavfi/fetcher.d.ts +7 -0
- package/lib/services/octavfi/fetcher.js +25 -0
- package/lib/services/octavfi/utils.d.ts +12 -0
- package/lib/services/octavfi/utils.js +44 -10
- package/lib/services/subgraph/fetcher.js +4 -2
- package/lib/services/subgraph/vaults.d.ts +12 -0
- package/lib/services/subgraph/vaults.js +43 -2
- package/lib/services/swap-quotes/index.d.ts +71 -0
- package/lib/services/swap-quotes/index.js +25 -0
- package/lib/services/swap-quotes/paraswap.d.ts +17 -0
- package/lib/services/swap-quotes/paraswap.js +14 -0
- package/lib/types/pools.d.ts +3 -0
- package/lib/types/typed-contract.d.ts +64 -0
- package/lib/types/vaults.d.ts +139 -2
- package/lib/types/vaults.js +10 -0
- package/lib/types/web3.d.ts +8 -0
- package/lib/types/web3.js +1 -0
- package/lib/types/webserver.d.ts +45 -0
- package/package.json +6 -5
|
@@ -7,6 +7,9 @@ const fallbackDecimals = 8;
|
|
|
7
7
|
exports.fallbackDecimals = fallbackDecimals;
|
|
8
8
|
const fallbackNetwork = 'mainnet-beta';
|
|
9
9
|
exports.fallbackNetwork = fallbackNetwork;
|
|
10
|
+
// ============================================================================
|
|
11
|
+
// SOLANA CONFIGURATION
|
|
12
|
+
// ============================================================================
|
|
10
13
|
const fallbackRpcEndpoints = {
|
|
11
14
|
devnet: 'https://api.devnet.solana.com',
|
|
12
15
|
mainnet: 'https://api.mainnet-beta.solana.com',
|
|
@@ -19,7 +22,7 @@ const programIds = {
|
|
|
19
22
|
vault: '7B8n9vL51b6ibqRAd1adZsi3x3kxtq5NZaondh22Vkyq',
|
|
20
23
|
},
|
|
21
24
|
['mainnet-beta']: {
|
|
22
|
-
vault: '7B8n9vL51b6ibqRAd1adZsi3x3kxtq5NZaondh22Vkyq',
|
|
25
|
+
vault: '7B8n9vL51b6ibqRAd1adZsi3x3kxtq5NZaondh22Vkyq', // BTCsyrup vault
|
|
23
26
|
},
|
|
24
27
|
testnet: {
|
|
25
28
|
vault: '7B8n9vL51b6ibqRAd1adZsi3x3kxtq5NZaondh22Vkyq',
|
|
@@ -1,3 +1,11 @@
|
|
|
1
1
|
import { ITokenizedVault } from '../../types';
|
|
2
2
|
import type { IVaultBaseOptions } from '../../modules/vaults/types';
|
|
3
|
+
/**
|
|
4
|
+
* Fetch Solana vault data from on-chain program state.
|
|
5
|
+
* Falls back to backend-only data when Solana RPC is unavailable,
|
|
6
|
+
* ensuring vaults always appear in the list even without on-chain access.
|
|
7
|
+
* @param tokenizedVault Vault metadata from backend
|
|
8
|
+
* @param options RPC configuration with Solana service
|
|
9
|
+
* @returns Formatted vault object with Solana-specific fields
|
|
10
|
+
*/
|
|
3
11
|
export declare const getSolanaVault: (tokenizedVault: ITokenizedVault, options: IVaultBaseOptions) => Promise<import("../../types").IVault>;
|
|
@@ -39,14 +39,24 @@ const utils_1 = require("./utils");
|
|
|
39
39
|
const SolanaConstants = __importStar(require("./constants"));
|
|
40
40
|
const core_1 = require("../../core");
|
|
41
41
|
const utils_2 = require("../../modules/vaults/utils");
|
|
42
|
+
/**
|
|
43
|
+
* Fetch Solana vault data from on-chain program state.
|
|
44
|
+
* Falls back to backend-only data when Solana RPC is unavailable,
|
|
45
|
+
* ensuring vaults always appear in the list even without on-chain access.
|
|
46
|
+
* @param tokenizedVault Vault metadata from backend
|
|
47
|
+
* @param options RPC configuration with Solana service
|
|
48
|
+
* @returns Formatted vault object with Solana-specific fields
|
|
49
|
+
*/
|
|
42
50
|
const getSolanaVault = async (tokenizedVault, options) => {
|
|
43
51
|
const solanaRpcUrl = options.rpcUrl;
|
|
44
52
|
const solanaMetadata = tokenizedVault.solana_vault_metadata;
|
|
45
53
|
const programId = utils_1.SolanaUtils.resolveProgramId(tokenizedVault.address, solanaMetadata);
|
|
54
|
+
// Fallback decimals: prefer backend metadata, then the application default
|
|
46
55
|
const fallbackDecimals = solanaMetadata?.deposit_token_decimals ?? SolanaConstants.fallbackDecimals;
|
|
47
56
|
let vaultState = null;
|
|
48
57
|
let depositMint = null;
|
|
49
58
|
let onChainAvailable = false;
|
|
59
|
+
// Attempt to fetch on-chain data; gracefully degrade if RPC is unavailable
|
|
50
60
|
try {
|
|
51
61
|
vaultState = await utils_1.SolanaUtils.getVaultStateReadOnly({
|
|
52
62
|
idl: SolanaConstants.vaultIdl,
|
|
@@ -70,6 +80,7 @@ const getSolanaVault = async (tokenizedVault, options) => {
|
|
|
70
80
|
}
|
|
71
81
|
}
|
|
72
82
|
catch (error) {
|
|
83
|
+
// Only degrade gracefully for network/RPC issues; re-throw everything else
|
|
73
84
|
const isNetworkError = error instanceof Error &&
|
|
74
85
|
(/fetch failed|ETIMEDOUT|timeout|ECONNREFUSED|403|503|network/i.test(error.message) ||
|
|
75
86
|
error.name === 'AbortError');
|
|
@@ -79,6 +90,9 @@ const getSolanaVault = async (tokenizedVault, options) => {
|
|
|
79
90
|
core_1.Logger.log.warn('getSolanaVault', 'RPC unavailable, using backend-only data', { vault: tokenizedVault.address, error });
|
|
80
91
|
}
|
|
81
92
|
const decimals = vaultState?.depositMintDecimals ?? fallbackDecimals;
|
|
93
|
+
// Fetch share mint supply to get totalSupply.
|
|
94
|
+
// Prefer vaultState.shareMint (correct for multi-vault programs like jitoSOL);
|
|
95
|
+
// fall back to deriveShareMintPda(programId) for legacy single-vault programs.
|
|
82
96
|
let totalSupply = (0, core_1.toNormalizedBn)(0, decimals);
|
|
83
97
|
if (onChainAvailable) {
|
|
84
98
|
try {
|
|
@@ -100,6 +114,11 @@ const getSolanaVault = async (tokenizedVault, options) => {
|
|
|
100
114
|
});
|
|
101
115
|
}
|
|
102
116
|
}
|
|
117
|
+
// Total assets must mirror the on-chain `VaultState::total_assets()` which
|
|
118
|
+
// is `local_aum + deployed_aum` (see solana-vaults/programs/august-vault/
|
|
119
|
+
// src/state/vault.rs). Reading deployed_aum alone makes the displayed share
|
|
120
|
+
// price drop below 1.0 the instant the operator deploys part of the vault,
|
|
121
|
+
// even though the vault has had no PnL.
|
|
103
122
|
let totalAssets;
|
|
104
123
|
if (onChainAvailable) {
|
|
105
124
|
const localAumRaw = vaultState?.vaultState?.localAum;
|
|
@@ -115,6 +134,7 @@ const getSolanaVault = async (tokenizedVault, options) => {
|
|
|
115
134
|
else {
|
|
116
135
|
totalAssets = (0, utils_2.backendTvlToNormalizedBn)(tokenizedVault.latest_reported_tvl, decimals);
|
|
117
136
|
}
|
|
137
|
+
// Deposit asset: use on-chain data if available, otherwise backend metadata
|
|
118
138
|
const depositAsset = {
|
|
119
139
|
address: depositMint?.address ?? solanaMetadata?.deposit_mint,
|
|
120
140
|
symbol: depositMint?.symbol ?? solanaMetadata?.deposit_token_symbol,
|
|
@@ -125,6 +145,7 @@ const getSolanaVault = async (tokenizedVault, options) => {
|
|
|
125
145
|
vault: tokenizedVault.address,
|
|
126
146
|
});
|
|
127
147
|
}
|
|
148
|
+
// Build unified vault object combining on-chain and backend data
|
|
128
149
|
return (0, utils_2.buildBackendVault)(tokenizedVault, {
|
|
129
150
|
chainId: core_1.SPECIAL_CHAINS.solana.chainId,
|
|
130
151
|
version: 'sol-0',
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.vaultIdl = void 0;
|
|
4
|
+
// /**
|
|
5
|
+
// * Program IDL in camelCase format in order to be used in JS/TS.
|
|
6
|
+
// *
|
|
7
|
+
// * Note that this is only a type helper and is not the actual IDL. The original
|
|
8
|
+
// * IDL can be found at `target/idl/august_vault.json`.
|
|
9
|
+
// */
|
|
4
10
|
exports.vaultIdl = {
|
|
5
11
|
address: '7B8n9vL51b6ibqRAd1adZsi3x3kxtq5NZaondh22Vkyq',
|
|
6
12
|
metadata: {
|
|
@@ -990,6 +996,9 @@ exports.vaultIdl = {
|
|
|
990
996
|
name: 'VaultState',
|
|
991
997
|
type: {
|
|
992
998
|
kind: 'struct',
|
|
999
|
+
// Field order MUST match programs/august-vault/src/state/vault.rs:36
|
|
1000
|
+
// exactly. Borsh deserialization is positional; any reorder, addition,
|
|
1001
|
+
// or omission silently corrupts every field after the drift point.
|
|
993
1002
|
fields: [
|
|
994
1003
|
{
|
|
995
1004
|
name: 'operator',
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Solana Adapter for August SDK
|
|
3
|
+
*
|
|
4
|
+
* @module SolanaAdapter
|
|
5
|
+
*/
|
|
1
6
|
import * as SolanaConstants from './constants';
|
|
2
7
|
import * as SolanaGetters from './getters';
|
|
3
8
|
import * as SolanaActions from './vault.actions';
|
|
@@ -102,6 +107,16 @@ export declare const Solana: {
|
|
|
102
107
|
actions: typeof SolanaActions;
|
|
103
108
|
getters: typeof SolanaGetters;
|
|
104
109
|
};
|
|
110
|
+
/**
|
|
111
|
+
* Solana Adapter for August SDK
|
|
112
|
+
*
|
|
113
|
+
* @example
|
|
114
|
+
* To access the Solana adapter instance
|
|
115
|
+
* ```
|
|
116
|
+
* const sdk = new AugustSDK()
|
|
117
|
+
* sdk.solana.getVaultState()
|
|
118
|
+
* ```
|
|
119
|
+
*/
|
|
105
120
|
declare class SolanaAdapter {
|
|
106
121
|
private _endpoint;
|
|
107
122
|
private _network;
|
|
@@ -132,11 +147,51 @@ declare class SolanaAdapter {
|
|
|
132
147
|
getTokenSymbol(mintAddress: string | PublicKey): Promise<string>;
|
|
133
148
|
fetchUserTokenBalance(publicKey: PublicKey | string, depositMint: PublicKey | string): Promise<any>;
|
|
134
149
|
fetchUserShareBalance(publicKey: PublicKey | string, shareMint: PublicKey | string): Promise<any>;
|
|
150
|
+
/**
|
|
151
|
+
* BigInt-safe variant of {@link fetchUserShareBalance}. Returns the raw u64
|
|
152
|
+
* `amount` (as a base-units string) plus the mint's `decimals` (or `null`
|
|
153
|
+
* when the scale can't be determined — see Returns), so the caller can
|
|
154
|
+
* produce a correct `INormalizedNumber` without losing precision.
|
|
155
|
+
*
|
|
156
|
+
* Prefer this anywhere the result feeds BigInt math — positions, max-
|
|
157
|
+
* actions, redemption sizing, allowance checks. `fetchUserShareBalance`
|
|
158
|
+
* returns a JS-number `uiAmount` which silently encodes against 18 decimals
|
|
159
|
+
* when passed through `toNormalizedBn(value)` without an explicit decimals
|
|
160
|
+
* argument; that's exactly how the jitoSOL "missing position" regression
|
|
161
|
+
* manifested.
|
|
162
|
+
*
|
|
163
|
+
* RPC cost: 1 `getParsedTokenAccountsByOwner` call. Worst case ~150ms on a
|
|
164
|
+
* healthy mainnet endpoint.
|
|
165
|
+
*
|
|
166
|
+
* @param publicKey Wallet owner (PublicKey or base58 string).
|
|
167
|
+
* @param shareMint The vault's share-token mint (PublicKey or base58).
|
|
168
|
+
* @returns
|
|
169
|
+
* `{ amount, decimals }`. Three observable shapes:
|
|
170
|
+
* - `{ amount: '<u64>', decimals: <number> }` — token account exists.
|
|
171
|
+
* - `{ amount: '0', decimals: null }` — no token account for this mint
|
|
172
|
+
* under this wallet, OR `tokenAmount` was missing from the response,
|
|
173
|
+
* OR `publicKey`/`shareMint` was not supplied. Distinguishable from a
|
|
174
|
+
* genuine zero-balance account (`decimals` would be set there).
|
|
175
|
+
* - `{ amount: '0', decimals: null }` — RPC threw (error is logged).
|
|
176
|
+
*
|
|
177
|
+
* `decimals === null` means "we could not determine the scale" — callers
|
|
178
|
+
* that need an `INormalizedNumber` must fall back to a known decimals
|
|
179
|
+
* value (typically the deposit mint's decimals from backend metadata)
|
|
180
|
+
* before normalizing. Never throws.
|
|
181
|
+
*/
|
|
135
182
|
fetchUserShareBalanceRaw(publicKey: PublicKey | string, shareMint: PublicKey | string): Promise<{
|
|
136
183
|
amount: string;
|
|
137
184
|
decimals: number | null;
|
|
138
185
|
}>;
|
|
186
|
+
/**
|
|
187
|
+
* Deposit funds into a Solana August vault.
|
|
188
|
+
* @param depositAmount `bigint` (raw on-chain units) or `number` (UI amount).
|
|
189
|
+
*/
|
|
139
190
|
vaultDeposit(vaultProgramId: PublicKey | string, idl: any, publicKey: PublicKey | string, depositAmount: number | bigint, sendTransaction: (transaction: Transaction | web3.VersionedTransaction, connection: Connection, options?: SendTransactionOptions) => Promise<web3.TransactionSignature>, vaultAddress?: PublicKey | string): Promise<any>;
|
|
191
|
+
/**
|
|
192
|
+
* Redeem vault shares from a Solana August vault.
|
|
193
|
+
* @param redeemShares `bigint` (raw share units) or `number` (UI amount).
|
|
194
|
+
*/
|
|
140
195
|
vaultRedeem(vaultProgramId: PublicKey | string, idl: any, publicKey: PublicKey | string, redeemShares: number | bigint, sendTransaction: (transaction: Transaction | web3.VersionedTransaction, connection: Connection, options?: SendTransactionOptions) => Promise<web3.TransactionSignature>, vaultAddress?: PublicKey | string): Promise<any>;
|
|
141
196
|
getProgramId(type: 'vault'): string;
|
|
142
197
|
}
|
|
@@ -34,6 +34,11 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.Solana = void 0;
|
|
37
|
+
/**
|
|
38
|
+
* Solana Adapter for August SDK
|
|
39
|
+
*
|
|
40
|
+
* @module SolanaAdapter
|
|
41
|
+
*/
|
|
37
42
|
const SolanaConstants = __importStar(require("./constants"));
|
|
38
43
|
const SolanaGetters = __importStar(require("./getters"));
|
|
39
44
|
const SolanaActions = __importStar(require("./vault.actions"));
|
|
@@ -47,6 +52,16 @@ exports.Solana = {
|
|
|
47
52
|
actions: SolanaActions,
|
|
48
53
|
getters: SolanaGetters,
|
|
49
54
|
};
|
|
55
|
+
/**
|
|
56
|
+
* Solana Adapter for August SDK
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* To access the Solana adapter instance
|
|
60
|
+
* ```
|
|
61
|
+
* const sdk = new AugustSDK()
|
|
62
|
+
* sdk.solana.getVaultState()
|
|
63
|
+
* ```
|
|
64
|
+
*/
|
|
50
65
|
class SolanaAdapter {
|
|
51
66
|
constructor(endpoint, network = utils_1.SolanaUtils.fallbackNetwork) {
|
|
52
67
|
this._endpoint = endpoint;
|
|
@@ -58,6 +73,7 @@ class SolanaAdapter {
|
|
|
58
73
|
connection,
|
|
59
74
|
});
|
|
60
75
|
}
|
|
76
|
+
// Getters and setters for private properties
|
|
61
77
|
get endpoint() {
|
|
62
78
|
return this._endpoint;
|
|
63
79
|
}
|
|
@@ -70,6 +86,7 @@ class SolanaAdapter {
|
|
|
70
86
|
get provider() {
|
|
71
87
|
return this._provider;
|
|
72
88
|
}
|
|
89
|
+
// Method to set connection with wallet for authenticated operations
|
|
73
90
|
setWalletProvider(_publicKey, signTransaction) {
|
|
74
91
|
if (_publicKey && signTransaction) {
|
|
75
92
|
const publicKey = typeof _publicKey === 'string' ? new web3_js_1.PublicKey(_publicKey) : _publicKey;
|
|
@@ -143,6 +160,38 @@ class SolanaAdapter {
|
|
|
143
160
|
shareMint,
|
|
144
161
|
});
|
|
145
162
|
}
|
|
163
|
+
/**
|
|
164
|
+
* BigInt-safe variant of {@link fetchUserShareBalance}. Returns the raw u64
|
|
165
|
+
* `amount` (as a base-units string) plus the mint's `decimals` (or `null`
|
|
166
|
+
* when the scale can't be determined — see Returns), so the caller can
|
|
167
|
+
* produce a correct `INormalizedNumber` without losing precision.
|
|
168
|
+
*
|
|
169
|
+
* Prefer this anywhere the result feeds BigInt math — positions, max-
|
|
170
|
+
* actions, redemption sizing, allowance checks. `fetchUserShareBalance`
|
|
171
|
+
* returns a JS-number `uiAmount` which silently encodes against 18 decimals
|
|
172
|
+
* when passed through `toNormalizedBn(value)` without an explicit decimals
|
|
173
|
+
* argument; that's exactly how the jitoSOL "missing position" regression
|
|
174
|
+
* manifested.
|
|
175
|
+
*
|
|
176
|
+
* RPC cost: 1 `getParsedTokenAccountsByOwner` call. Worst case ~150ms on a
|
|
177
|
+
* healthy mainnet endpoint.
|
|
178
|
+
*
|
|
179
|
+
* @param publicKey Wallet owner (PublicKey or base58 string).
|
|
180
|
+
* @param shareMint The vault's share-token mint (PublicKey or base58).
|
|
181
|
+
* @returns
|
|
182
|
+
* `{ amount, decimals }`. Three observable shapes:
|
|
183
|
+
* - `{ amount: '<u64>', decimals: <number> }` — token account exists.
|
|
184
|
+
* - `{ amount: '0', decimals: null }` — no token account for this mint
|
|
185
|
+
* under this wallet, OR `tokenAmount` was missing from the response,
|
|
186
|
+
* OR `publicKey`/`shareMint` was not supplied. Distinguishable from a
|
|
187
|
+
* genuine zero-balance account (`decimals` would be set there).
|
|
188
|
+
* - `{ amount: '0', decimals: null }` — RPC threw (error is logged).
|
|
189
|
+
*
|
|
190
|
+
* `decimals === null` means "we could not determine the scale" — callers
|
|
191
|
+
* that need an `INormalizedNumber` must fall back to a known decimals
|
|
192
|
+
* value (typically the deposit mint's decimals from backend metadata)
|
|
193
|
+
* before normalizing. Never throws.
|
|
194
|
+
*/
|
|
146
195
|
async fetchUserShareBalanceRaw(publicKey, shareMint) {
|
|
147
196
|
return await utils_1.SolanaUtils.fetchUserShareBalanceRaw({
|
|
148
197
|
network: this._network,
|
|
@@ -151,6 +200,10 @@ class SolanaAdapter {
|
|
|
151
200
|
shareMint,
|
|
152
201
|
});
|
|
153
202
|
}
|
|
203
|
+
/**
|
|
204
|
+
* Deposit funds into a Solana August vault.
|
|
205
|
+
* @param depositAmount `bigint` (raw on-chain units) or `number` (UI amount).
|
|
206
|
+
*/
|
|
154
207
|
async vaultDeposit(vaultProgramId, idl, publicKey, depositAmount, sendTransaction, vaultAddress) {
|
|
155
208
|
return await (0, vault_actions_1.handleSolanaDeposit)({
|
|
156
209
|
network: this._network,
|
|
@@ -164,6 +217,10 @@ class SolanaAdapter {
|
|
|
164
217
|
sendTransaction,
|
|
165
218
|
});
|
|
166
219
|
}
|
|
220
|
+
/**
|
|
221
|
+
* Redeem vault shares from a Solana August vault.
|
|
222
|
+
* @param redeemShares `bigint` (raw share units) or `number` (UI amount).
|
|
223
|
+
*/
|
|
167
224
|
async vaultRedeem(vaultProgramId, idl, publicKey, redeemShares, sendTransaction, vaultAddress) {
|
|
168
225
|
return await (0, vault_actions_1.handleSolanaRedeem)({
|
|
169
226
|
network: this._network,
|
|
@@ -66,6 +66,28 @@ declare function fetchUserShareBalance({ connection, publicKey, shareMint, }: {
|
|
|
66
66
|
publicKey: PublicKey | string;
|
|
67
67
|
shareMint?: PublicKey | string;
|
|
68
68
|
} & ISolanaConnectionOptions): Promise<any>;
|
|
69
|
+
/**
|
|
70
|
+
* Same on-chain lookup as `fetchUserShareBalance`, but returns the raw u64
|
|
71
|
+
* `amount` string and the mint's `decimals` — or `null` when the scale can't
|
|
72
|
+
* be determined (see Return shape) — instead of the floating-point `uiAmount`.
|
|
73
|
+
* Callers that feed the result into BigInt math (positions, redemptions,
|
|
74
|
+
* allowances) must use this — `uiAmount` is lossy and silently encodes with
|
|
75
|
+
* the wrong scale when passed back through `toNormalizedBn` without an
|
|
76
|
+
* explicit decimals argument.
|
|
77
|
+
*
|
|
78
|
+
* Return shape:
|
|
79
|
+
* `{ amount: '<u64>', decimals: number }` — token account exists.
|
|
80
|
+
* `{ amount: '0', decimals: null }` — no token account, missing
|
|
81
|
+
* tokenAmount in the parsed response, missing args, or the RPC threw.
|
|
82
|
+
*
|
|
83
|
+
* `decimals === null` is the "scale unknown" signal — callers that need a
|
|
84
|
+
* normalized `INormalizedNumber` must substitute a known decimals value
|
|
85
|
+
* (typically the deposit mint's decimals from backend metadata) before
|
|
86
|
+
* normalizing. Never throws.
|
|
87
|
+
*
|
|
88
|
+
* RPC cost: 1 × `getParsedTokenAccountsByOwner`. Independent of how many
|
|
89
|
+
* other accounts the wallet owns (filter is mint-scoped).
|
|
90
|
+
*/
|
|
69
91
|
declare function fetchUserShareBalanceRaw({ connection, publicKey, shareMint, }: {
|
|
70
92
|
publicKey: PublicKey | string;
|
|
71
93
|
shareMint?: PublicKey | string;
|
|
@@ -73,9 +95,15 @@ declare function fetchUserShareBalanceRaw({ connection, publicKey, shareMint, }:
|
|
|
73
95
|
amount: string;
|
|
74
96
|
decimals: number | null;
|
|
75
97
|
}>;
|
|
98
|
+
/**
|
|
99
|
+
* Resolve the on-chain program ID for a Solana vault.
|
|
100
|
+
* Prefers the explicit `program_id` from metadata; falls back to the vault address
|
|
101
|
+
* (for legacy vaults where address == program ID).
|
|
102
|
+
*/
|
|
76
103
|
declare function resolveProgramId(vaultAddress: string, solanaMetadata?: {
|
|
77
104
|
program_id?: string;
|
|
78
105
|
} | null): string;
|
|
106
|
+
/** @internal */
|
|
79
107
|
export declare function uiAmountToRawBn(uiAmount: number, decimals: number): BN;
|
|
80
108
|
export declare const SolanaUtils: {
|
|
81
109
|
getExplorerLink: typeof getExplorerLink;
|
|
@@ -7,31 +7,42 @@ const web3_js_1 = require("@solana/web3.js");
|
|
|
7
7
|
const ethers_1 = require("ethers");
|
|
8
8
|
const constants_1 = require("./constants");
|
|
9
9
|
const core_1 = require("../../core");
|
|
10
|
+
// ============================================================================
|
|
11
|
+
// SOLANA UTILITIES
|
|
12
|
+
// ============================================================================
|
|
10
13
|
function getExplorerLink({ signature, type = 'tx', network = constants_1.fallbackNetwork, }) {
|
|
11
14
|
const baseUrl = 'https://solscan.io';
|
|
12
15
|
return `${baseUrl}/${type}/${signature}?cluster=${network}`;
|
|
13
16
|
}
|
|
17
|
+
// Re-exported from the core leaf so consumers in the core layer can import it
|
|
18
|
+
// without taking a dependency on the Solana adapter.
|
|
14
19
|
const chain_address_1 = require("../../core/helpers/chain-address");
|
|
15
20
|
Object.defineProperty(exports, "isSolanaAddress", { enumerable: true, get: function () { return chain_address_1.isSolanaAddress; } });
|
|
16
21
|
function isSolana(signature) {
|
|
17
22
|
if (!signature || typeof signature !== 'string')
|
|
18
23
|
return false;
|
|
24
|
+
// Check if it's an Ethereum address first
|
|
19
25
|
if ((0, ethers_1.isAddress)(signature))
|
|
20
26
|
return false;
|
|
27
|
+
// Check if it's a valid Solana address (including PDAs) — addresses are not signatures
|
|
21
28
|
if ((0, chain_address_1.isSolanaAddress)(signature))
|
|
22
29
|
return false;
|
|
30
|
+
// Check if it's a valid base58 string with correct length for Solana signatures
|
|
31
|
+
// Solana signatures are base58 encoded and typically 88 characters long
|
|
23
32
|
const base58Chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
|
|
24
33
|
const isValidBase58 = signature
|
|
25
34
|
.split('')
|
|
26
35
|
.every((char) => base58Chars.includes(char));
|
|
27
36
|
if (!isValidBase58)
|
|
28
37
|
return false;
|
|
38
|
+
// Check length - Solana signatures are typically 88 characters
|
|
29
39
|
return (signature.length >= 80 && signature.length <= 100);
|
|
30
40
|
}
|
|
31
41
|
function getProgram({ provider, idl, programId, network, }) {
|
|
32
42
|
if (!idl) {
|
|
33
43
|
return new anchor_1.Program(constants_1.vaultIdl, provider);
|
|
34
44
|
}
|
|
45
|
+
// If programId is provided, create a modified IDL with the correct address
|
|
35
46
|
if (programId) {
|
|
36
47
|
const modifiedIdl = {
|
|
37
48
|
...idl,
|
|
@@ -41,6 +52,9 @@ function getProgram({ provider, idl, programId, network, }) {
|
|
|
41
52
|
}
|
|
42
53
|
return new anchor_1.Program(idl, provider);
|
|
43
54
|
}
|
|
55
|
+
// ============================================================================
|
|
56
|
+
// SOLANA PROVIDERS
|
|
57
|
+
// ============================================================================
|
|
44
58
|
async function testRpcEndpoint({ connection }) {
|
|
45
59
|
try {
|
|
46
60
|
const blockHeight = await connection.getBlockHeight();
|
|
@@ -50,13 +64,16 @@ async function testRpcEndpoint({ connection }) {
|
|
|
50
64
|
return { success: false, error };
|
|
51
65
|
}
|
|
52
66
|
}
|
|
67
|
+
// Function to get the best available RPC endpoint
|
|
53
68
|
async function getBestRpcEndpoint({ endpoint, network = constants_1.fallbackNetwork, connection, }) {
|
|
54
69
|
const primaryEndpoint = endpoint;
|
|
55
70
|
const fallbackEndpoint = constants_1.fallbackRpcEndpoints[network];
|
|
71
|
+
// Test primary endpoint first
|
|
56
72
|
const primaryTest = await testRpcEndpoint({ connection });
|
|
57
73
|
if (primaryTest.success) {
|
|
58
74
|
return primaryEndpoint;
|
|
59
75
|
}
|
|
76
|
+
// Fall back to public endpoint
|
|
60
77
|
core_1.Logger.log.warn('getBestRpcEndpoint', '⚠️ Primary RPC endpoint failed, using fallback:', fallbackEndpoint);
|
|
61
78
|
return fallbackEndpoint;
|
|
62
79
|
}
|
|
@@ -68,14 +85,17 @@ function getProvider({ connection, publicKey, signTransaction, }) {
|
|
|
68
85
|
publicKey,
|
|
69
86
|
signTransaction,
|
|
70
87
|
signAllTransactions: async (txs) => {
|
|
88
|
+
// Use Promise.all instead of await in loop
|
|
71
89
|
const signedTransactions = await Promise.all(txs.map(async (tx) => signTransaction(tx)));
|
|
72
90
|
return signedTransactions;
|
|
73
91
|
},
|
|
74
92
|
}, { commitment: 'confirmed' });
|
|
75
93
|
}
|
|
94
|
+
// Read-only provider for data fetching without wallet connection
|
|
76
95
|
function getReadOnlyProvider({ connection }) {
|
|
96
|
+
// Create a dummy wallet object for read-only operations
|
|
77
97
|
const dummyWallet = {
|
|
78
|
-
publicKey: web3_js_1.PublicKey.default,
|
|
98
|
+
publicKey: web3_js_1.PublicKey.default, // Use default public key
|
|
79
99
|
signTransaction: async (_tx) => {
|
|
80
100
|
throw new core_1.AugustValidationError('INVALID_INPUT', 'Cannot sign transactions with read-only provider');
|
|
81
101
|
},
|
|
@@ -87,6 +107,9 @@ function getReadOnlyProvider({ connection }) {
|
|
|
87
107
|
commitment: 'confirmed',
|
|
88
108
|
});
|
|
89
109
|
}
|
|
110
|
+
// ============================================================================
|
|
111
|
+
// SOLANA DERIVATIONS
|
|
112
|
+
// ============================================================================
|
|
90
113
|
function deriveVaultStatePda(vaultProgramId) {
|
|
91
114
|
if (!vaultProgramId)
|
|
92
115
|
throw new core_1.AugustValidationError('INVALID_INPUT', 'Vault program ID missing');
|
|
@@ -120,6 +143,9 @@ function deriveVaultTokenAtaPda(vaultProgramId, depositMint, vaultVersion) {
|
|
|
120
143
|
const [pda] = web3_js_1.PublicKey.findProgramAddressSync(seeds, _vaultProgramId);
|
|
121
144
|
return pda;
|
|
122
145
|
}
|
|
146
|
+
// ============================================================================
|
|
147
|
+
// SOLANA VAULTS
|
|
148
|
+
// ============================================================================
|
|
123
149
|
async function getVaultState({ provider, connection, vaultProgramId, vaultAddress, idl, }) {
|
|
124
150
|
const returnObj = {
|
|
125
151
|
vaultState: null,
|
|
@@ -169,6 +195,7 @@ async function getVaultState({ provider, connection, vaultProgramId, vaultAddres
|
|
|
169
195
|
return returnObj;
|
|
170
196
|
}
|
|
171
197
|
}
|
|
198
|
+
// Read-only version of getVaultState that works without wallet connection
|
|
172
199
|
async function getVaultStateReadOnly({ vaultProgramId, vaultAddress, connection, idl, }) {
|
|
173
200
|
const returnObj = {
|
|
174
201
|
vaultState: null,
|
|
@@ -186,11 +213,13 @@ async function getVaultStateReadOnly({ vaultProgramId, vaultAddress, connection,
|
|
|
186
213
|
const vaultStatePda = vaultAddress
|
|
187
214
|
? new web3_js_1.PublicKey(vaultAddress)
|
|
188
215
|
: deriveVaultStatePda(_vaultProgramId);
|
|
216
|
+
// Use connection directly to fetch account data
|
|
189
217
|
const accountInfo = await connection.getAccountInfo(vaultStatePda);
|
|
190
218
|
if (!accountInfo) {
|
|
191
219
|
core_1.Logger.log.warn('getVaultStateReadOnly', 'Vault state account not found');
|
|
192
220
|
return returnObj;
|
|
193
221
|
}
|
|
222
|
+
// Try to create a program with read-only provider for parsing
|
|
194
223
|
try {
|
|
195
224
|
const readOnlyProvider = getReadOnlyProvider({ connection });
|
|
196
225
|
const program = getProgram({
|
|
@@ -219,6 +248,7 @@ async function getVaultStateReadOnly({ vaultProgramId, vaultAddress, connection,
|
|
|
219
248
|
core_1.Logger.log.error('getVaultStateReadOnly', programError, {
|
|
220
249
|
message: 'Error creating program with read-only provider',
|
|
221
250
|
});
|
|
251
|
+
// Fallback: program parsing failed, vault state is unavailable
|
|
222
252
|
returnObj.vaultState = null;
|
|
223
253
|
}
|
|
224
254
|
await (0, core_1.setSafeCache)(cacheKey, returnObj);
|
|
@@ -232,6 +262,7 @@ async function getVaultStateReadOnly({ vaultProgramId, vaultAddress, connection,
|
|
|
232
262
|
return returnObj;
|
|
233
263
|
}
|
|
234
264
|
}
|
|
265
|
+
// Fetch deposit and share mint addresses from on-chain vault state (read-only, no wallet required)
|
|
235
266
|
async function getVaultMints({ vaultProgramId, vaultAddress, connection, idl, }) {
|
|
236
267
|
try {
|
|
237
268
|
const cacheKey = `vaultMints-${vaultAddress || vaultProgramId}`;
|
|
@@ -255,6 +286,7 @@ async function getVaultMints({ vaultProgramId, vaultAddress, connection, idl, })
|
|
|
255
286
|
const returnObj = {
|
|
256
287
|
depositMint: state.depositMint.toString(),
|
|
257
288
|
shareMint: state.shareMint.toString(),
|
|
289
|
+
// Empty arrays yield undefined, falling back to legacy PDA seeds (no version byte)
|
|
258
290
|
vaultVersion: Array.isArray(state.vaultVersion)
|
|
259
291
|
? state.vaultVersion[0]
|
|
260
292
|
: undefined,
|
|
@@ -285,6 +317,7 @@ async function getToken({ mintAddress, endpoint, connection, }) {
|
|
|
285
317
|
const cachedData = await (0, core_1.getSafeCache)(cacheKey);
|
|
286
318
|
if (cachedData)
|
|
287
319
|
return cachedData;
|
|
320
|
+
// First, try to get token metadata via Metaplex DAS API
|
|
288
321
|
const response = await fetch(endpoint, {
|
|
289
322
|
method: 'POST',
|
|
290
323
|
headers: {
|
|
@@ -297,7 +330,8 @@ async function getToken({ mintAddress, endpoint, connection, }) {
|
|
|
297
330
|
params: { id: mintAddress.toString() },
|
|
298
331
|
}),
|
|
299
332
|
});
|
|
300
|
-
const data = (await response.json());
|
|
333
|
+
const data = (await response.json()); // @todo: add interface
|
|
334
|
+
// If we got valid token metadata, return it
|
|
301
335
|
if (data.result?.token_info?.decimals !== undefined) {
|
|
302
336
|
return {
|
|
303
337
|
address: data?.result?.id,
|
|
@@ -311,19 +345,25 @@ async function getToken({ mintAddress, endpoint, connection, }) {
|
|
|
311
345
|
supply: data.result?.token_info?.supply,
|
|
312
346
|
};
|
|
313
347
|
}
|
|
348
|
+
// If Metaplex metadata didn't work, check if this is a vault program address
|
|
349
|
+
// In that case, we should query the share mint PDA instead
|
|
314
350
|
if (connection) {
|
|
315
351
|
try {
|
|
316
352
|
const vaultProgramId = new web3_js_1.PublicKey(mintAddress);
|
|
353
|
+
// Try to get vault state to see if this is a vault
|
|
317
354
|
const vaultState = await getVaultStateReadOnly({
|
|
318
355
|
vaultProgramId,
|
|
319
356
|
connection,
|
|
320
357
|
idl: constants_1.vaultIdl,
|
|
321
358
|
});
|
|
359
|
+
// If we successfully got vault state, derive the share mint and query that
|
|
322
360
|
if (vaultState.vaultState) {
|
|
323
361
|
const shareMintPda = deriveShareMintPda(vaultProgramId);
|
|
362
|
+
// Get share mint metadata from blockchain
|
|
324
363
|
const shareMintInfo = await connection.getParsedAccountInfo(shareMintPda);
|
|
325
364
|
if (shareMintInfo.value) {
|
|
326
365
|
const parsedData = shareMintInfo.value.data;
|
|
366
|
+
// Try to get Metaplex metadata for the share mint
|
|
327
367
|
const shareMintMetadata = await fetch(endpoint, {
|
|
328
368
|
method: 'POST',
|
|
329
369
|
headers: {
|
|
@@ -338,7 +378,7 @@ async function getToken({ mintAddress, endpoint, connection, }) {
|
|
|
338
378
|
});
|
|
339
379
|
const shareMintData = (await shareMintMetadata.json());
|
|
340
380
|
const returnObj = {
|
|
341
|
-
address: mintAddress.toString(),
|
|
381
|
+
address: mintAddress.toString(), // Return original vault address
|
|
342
382
|
symbol: shareMintData.result?.content?.metadata?.symbol || 'N/A',
|
|
343
383
|
decimals: parsedData.parsed.info.decimals,
|
|
344
384
|
name: shareMintData.result?.content?.metadata?.name ||
|
|
@@ -348,7 +388,7 @@ async function getToken({ mintAddress, endpoint, connection, }) {
|
|
|
348
388
|
mintAuthority: shareMintData.result?.token_info?.mint_authority,
|
|
349
389
|
freezeAuthority: shareMintData.result?.token_info?.freeze_authority,
|
|
350
390
|
supply: parsedData.parsed.info.supply,
|
|
351
|
-
shareMintAddress: shareMintPda.toString(),
|
|
391
|
+
shareMintAddress: shareMintPda.toString(), // Include share mint address
|
|
352
392
|
};
|
|
353
393
|
await (0, core_1.setSafeCache)(cacheKey, returnObj);
|
|
354
394
|
return returnObj;
|
|
@@ -356,9 +396,11 @@ async function getToken({ mintAddress, endpoint, connection, }) {
|
|
|
356
396
|
}
|
|
357
397
|
}
|
|
358
398
|
catch (vaultError) {
|
|
399
|
+
// Not a vault or error checking vault state, continue to return null
|
|
359
400
|
core_1.Logger.log.info('getToken', 'Not a vault program or error querying vault:', vaultError);
|
|
360
401
|
}
|
|
361
402
|
}
|
|
403
|
+
// If all attempts failed, return null
|
|
362
404
|
return null;
|
|
363
405
|
}
|
|
364
406
|
catch (error) {
|
|
@@ -368,6 +410,7 @@ async function getToken({ mintAddress, endpoint, connection, }) {
|
|
|
368
410
|
return null;
|
|
369
411
|
}
|
|
370
412
|
}
|
|
413
|
+
// Helper function to get just the token symbol
|
|
371
414
|
async function getTokenSymbol({ endpoint, mintAddress, }) {
|
|
372
415
|
try {
|
|
373
416
|
const tokenMetadata = await getToken({ endpoint, mintAddress });
|
|
@@ -431,6 +474,28 @@ async function fetchUserShareBalance({ connection, publicKey, shareMint, }) {
|
|
|
431
474
|
return 0;
|
|
432
475
|
}
|
|
433
476
|
}
|
|
477
|
+
/**
|
|
478
|
+
* Same on-chain lookup as `fetchUserShareBalance`, but returns the raw u64
|
|
479
|
+
* `amount` string and the mint's `decimals` — or `null` when the scale can't
|
|
480
|
+
* be determined (see Return shape) — instead of the floating-point `uiAmount`.
|
|
481
|
+
* Callers that feed the result into BigInt math (positions, redemptions,
|
|
482
|
+
* allowances) must use this — `uiAmount` is lossy and silently encodes with
|
|
483
|
+
* the wrong scale when passed back through `toNormalizedBn` without an
|
|
484
|
+
* explicit decimals argument.
|
|
485
|
+
*
|
|
486
|
+
* Return shape:
|
|
487
|
+
* `{ amount: '<u64>', decimals: number }` — token account exists.
|
|
488
|
+
* `{ amount: '0', decimals: null }` — no token account, missing
|
|
489
|
+
* tokenAmount in the parsed response, missing args, or the RPC threw.
|
|
490
|
+
*
|
|
491
|
+
* `decimals === null` is the "scale unknown" signal — callers that need a
|
|
492
|
+
* normalized `INormalizedNumber` must substitute a known decimals value
|
|
493
|
+
* (typically the deposit mint's decimals from backend metadata) before
|
|
494
|
+
* normalizing. Never throws.
|
|
495
|
+
*
|
|
496
|
+
* RPC cost: 1 × `getParsedTokenAccountsByOwner`. Independent of how many
|
|
497
|
+
* other accounts the wallet owns (filter is mint-scoped).
|
|
498
|
+
*/
|
|
434
499
|
async function fetchUserShareBalanceRaw({ connection, publicKey, shareMint, }) {
|
|
435
500
|
if (!publicKey || !shareMint)
|
|
436
501
|
return { amount: '0', decimals: null };
|
|
@@ -456,9 +521,17 @@ async function fetchUserShareBalanceRaw({ connection, publicKey, shareMint, }) {
|
|
|
456
521
|
return { amount: '0', decimals: null };
|
|
457
522
|
}
|
|
458
523
|
}
|
|
524
|
+
/**
|
|
525
|
+
* Resolve the on-chain program ID for a Solana vault.
|
|
526
|
+
* Prefers the explicit `program_id` from metadata; falls back to the vault address
|
|
527
|
+
* (for legacy vaults where address == program ID).
|
|
528
|
+
*/
|
|
459
529
|
function resolveProgramId(vaultAddress, solanaMetadata) {
|
|
460
530
|
return solanaMetadata?.program_id || vaultAddress;
|
|
461
531
|
}
|
|
532
|
+
// String-arithmetic UI→raw conversion. Truncates past `decimals` like
|
|
533
|
+
// ethers.parseUnits; safe past Number.MAX_SAFE_INTEGER.
|
|
534
|
+
/** @internal */
|
|
462
535
|
function uiAmountToRawBn(uiAmount, decimals) {
|
|
463
536
|
if (!Number.isFinite(uiAmount)) {
|
|
464
537
|
throw new core_1.AugustValidationError('INVALID_INPUT', `uiAmountToRawBn: amount must be finite, got ${uiAmount}`);
|
|
@@ -469,6 +542,8 @@ function uiAmountToRawBn(uiAmount, decimals) {
|
|
|
469
542
|
if (!Number.isInteger(decimals) || decimals < 0) {
|
|
470
543
|
throw new core_1.AugustValidationError('INVALID_INPUT', `uiAmountToRawBn: decimals must be a non-negative integer, got ${decimals}`);
|
|
471
544
|
}
|
|
545
|
+
// Build the fixed-decimal string manually — `.toFixed(decimals)` rounds
|
|
546
|
+
// the last digit, but parseUnits semantics require truncation.
|
|
472
547
|
const uiStr = uiAmount.toString();
|
|
473
548
|
const expansion = uiStr.includes('e') || uiStr.includes('E')
|
|
474
549
|
? uiAmount.toFixed(Math.max(decimals, 20)).replace(/\.?0+$/, '')
|
|
@@ -2,6 +2,17 @@ import { web3 } from '@coral-xyz/anchor';
|
|
|
2
2
|
import { Connection, PublicKey, Transaction } from '@solana/web3.js';
|
|
3
3
|
import { ISolanaConnectionOptions } from './types';
|
|
4
4
|
import { SendTransactionOptions } from '@solana/wallet-adapter-base';
|
|
5
|
+
/**
|
|
6
|
+
* Deposit funds into a Solana August vault and mint share tokens.
|
|
7
|
+
*
|
|
8
|
+
* @param depositAmount `bigint` is treated as raw on-chain units (preferred
|
|
9
|
+
* — no JS-float round-trip). `number` is treated as a UI amount and
|
|
10
|
+
* scaled by the deposit mint's decimals via {@link uiAmountToRawBn}.
|
|
11
|
+
* @throws AugustValidationError on missing wallet/programId or invalid amount.
|
|
12
|
+
* @remarks The on-chain `deposit` instruction has no `min_shares_out`
|
|
13
|
+
* parameter; slippage cannot be enforced on-chain until the program ships
|
|
14
|
+
* that argument.
|
|
15
|
+
*/
|
|
5
16
|
export declare function handleSolanaDeposit({ provider, connection, network, vaultProgramId, vaultAddress, depositAmount, publicKey, sendTransaction, idl, }: {
|
|
6
17
|
vaultProgramId: PublicKey | string;
|
|
7
18
|
vaultAddress?: PublicKey | string;
|
|
@@ -10,6 +21,14 @@ export declare function handleSolanaDeposit({ provider, connection, network, vau
|
|
|
10
21
|
depositAmount: number | bigint;
|
|
11
22
|
sendTransaction: (transaction: Transaction | web3.VersionedTransaction, connection: Connection, options?: SendTransactionOptions) => Promise<web3.TransactionSignature>;
|
|
12
23
|
} & ISolanaConnectionOptions): Promise<any>;
|
|
24
|
+
/**
|
|
25
|
+
* Redeem vault shares back into the underlying mint on a Solana August vault.
|
|
26
|
+
*
|
|
27
|
+
* @param redeemShares `bigint` is treated as raw share-token units;
|
|
28
|
+
* `number` is treated as a UI amount. See {@link handleSolanaDeposit} for
|
|
29
|
+
* the same caveat about the missing on-chain slippage guard.
|
|
30
|
+
* @throws AugustValidationError on missing wallet/programId or invalid amount.
|
|
31
|
+
*/
|
|
13
32
|
export declare function handleSolanaRedeem({ provider, connection, vaultProgramId, vaultAddress, publicKey, redeemShares, sendTransaction, idl, }: {
|
|
14
33
|
idl: any;
|
|
15
34
|
vaultProgramId: PublicKey | string;
|