@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
|
@@ -8,6 +8,17 @@ const spl_token_1 = require("@solana/spl-token");
|
|
|
8
8
|
const constants_1 = require("./constants");
|
|
9
9
|
const utils_1 = require("./utils");
|
|
10
10
|
const core_1 = require("../../core");
|
|
11
|
+
/**
|
|
12
|
+
* Deposit funds into a Solana August vault and mint share tokens.
|
|
13
|
+
*
|
|
14
|
+
* @param depositAmount `bigint` is treated as raw on-chain units (preferred
|
|
15
|
+
* — no JS-float round-trip). `number` is treated as a UI amount and
|
|
16
|
+
* scaled by the deposit mint's decimals via {@link uiAmountToRawBn}.
|
|
17
|
+
* @throws AugustValidationError on missing wallet/programId or invalid amount.
|
|
18
|
+
* @remarks The on-chain `deposit` instruction has no `min_shares_out`
|
|
19
|
+
* parameter; slippage cannot be enforced on-chain until the program ships
|
|
20
|
+
* that argument.
|
|
21
|
+
*/
|
|
11
22
|
async function handleSolanaDeposit({ provider, connection, network = constants_1.fallbackNetwork, vaultProgramId, vaultAddress, depositAmount, publicKey, sendTransaction, idl, }) {
|
|
12
23
|
try {
|
|
13
24
|
if (!publicKey)
|
|
@@ -44,8 +55,11 @@ async function handleSolanaDeposit({ provider, connection, network = constants_1
|
|
|
44
55
|
core_1.Logger.log.info('handleSolanaDeposit', 'Vault state PDA', vaultStatePda.toBase58());
|
|
45
56
|
const vaultTokenAtaPda = utils_1.SolanaUtils.deriveVaultTokenAtaPda(_vaultProgramId, _depositMint, vaultVersion);
|
|
46
57
|
core_1.Logger.log.info('handleSolanaDeposit', 'Vault token ATA PDA', vaultTokenAtaPda.toBase58());
|
|
58
|
+
// Use on-chain share mint from vault state instead of deriving a PDA,
|
|
59
|
+
// since PDA derivation assumes one share mint per program (single-vault only).
|
|
47
60
|
const shareMintAddr = new web3_js_1.PublicKey(shareMint);
|
|
48
61
|
core_1.Logger.log.info('handleSolanaDeposit', 'Share mint', shareMintAddr.toBase58());
|
|
62
|
+
// Get mint info to handle decimals
|
|
49
63
|
const mintInfo = await connection.getParsedAccountInfo(_depositMint);
|
|
50
64
|
if (!mintInfo.value) {
|
|
51
65
|
throw new Error('Could not fetch mint info');
|
|
@@ -64,6 +78,7 @@ async function handleSolanaDeposit({ provider, connection, network = constants_1
|
|
|
64
78
|
}
|
|
65
79
|
depositAmountRaw = (0, utils_1.uiAmountToRawBn)(depositAmount, decimals);
|
|
66
80
|
}
|
|
81
|
+
// Find user's token accounts
|
|
67
82
|
const userTokenAccounts = await connection.getParsedTokenAccountsByOwner(_publicKey, {
|
|
68
83
|
mint: _depositMint,
|
|
69
84
|
});
|
|
@@ -78,9 +93,14 @@ async function handleSolanaDeposit({ provider, connection, network = constants_1
|
|
|
78
93
|
let senderShareAccount;
|
|
79
94
|
if (userShareAccounts.value.length === 0) {
|
|
80
95
|
core_1.Logger.log.info('handleSolanaDeposit', 'Creating share account');
|
|
96
|
+
// Create share account if it doesn't exist
|
|
81
97
|
senderShareAccount = await (0, spl_token_1.getAssociatedTokenAddress)(shareMintAddr, _publicKey);
|
|
82
98
|
core_1.Logger.log.info('handleSolanaDeposit', 'Sender share account', senderShareAccount.toBase58());
|
|
83
|
-
|
|
99
|
+
// Create the associated token account
|
|
100
|
+
const createAtaIx = (0, spl_token_1.createAssociatedTokenAccountInstruction)(_publicKey, // payer
|
|
101
|
+
senderShareAccount, // associated token account
|
|
102
|
+
_publicKey, // owner
|
|
103
|
+
shareMintAddr);
|
|
84
104
|
core_1.Logger.log.info('handleSolanaDeposit', 'Create ATA Ix', createAtaIx.programId.toBase58());
|
|
85
105
|
const transaction = new web3_js_1.Transaction().add(createAtaIx);
|
|
86
106
|
const signature = await sendTransaction(transaction, connection);
|
|
@@ -100,7 +120,9 @@ async function handleSolanaDeposit({ provider, connection, network = constants_1
|
|
|
100
120
|
core_1.Logger.log.info('handleSolanaDeposit', 'Share mint', shareMintAddr.toBase58());
|
|
101
121
|
core_1.Logger.log.info('handleSolanaDeposit', 'Deposit mint', _depositMint?.toBase58());
|
|
102
122
|
core_1.Logger.log.info('handleSolanaDeposit', 'Signer', _publicKey.toBase58());
|
|
123
|
+
// Get a fresh blockhash to avoid "Blockhash not found" errors
|
|
103
124
|
const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash('confirmed');
|
|
125
|
+
// TODO(slippage): pass `min_shares_out` here when the program ships it.
|
|
104
126
|
const tx = await program.methods
|
|
105
127
|
.deposit(depositAmountRaw)
|
|
106
128
|
.accounts({
|
|
@@ -118,6 +140,7 @@ async function handleSolanaDeposit({ provider, connection, network = constants_1
|
|
|
118
140
|
preflightCommitment: 'confirmed',
|
|
119
141
|
});
|
|
120
142
|
core_1.Logger.log.info('handleSolanaDeposit', 'Deposit successful:', tx);
|
|
143
|
+
// Wait for confirmation with the blockhash we used
|
|
121
144
|
await connection.confirmTransaction({
|
|
122
145
|
signature: tx,
|
|
123
146
|
blockhash,
|
|
@@ -146,6 +169,14 @@ async function handleSolanaDeposit({ provider, connection, network = constants_1
|
|
|
146
169
|
});
|
|
147
170
|
}
|
|
148
171
|
}
|
|
172
|
+
/**
|
|
173
|
+
* Redeem vault shares back into the underlying mint on a Solana August vault.
|
|
174
|
+
*
|
|
175
|
+
* @param redeemShares `bigint` is treated as raw share-token units;
|
|
176
|
+
* `number` is treated as a UI amount. See {@link handleSolanaDeposit} for
|
|
177
|
+
* the same caveat about the missing on-chain slippage guard.
|
|
178
|
+
* @throws AugustValidationError on missing wallet/programId or invalid amount.
|
|
179
|
+
*/
|
|
149
180
|
async function handleSolanaRedeem({ provider, connection, vaultProgramId, vaultAddress, publicKey, redeemShares, sendTransaction, idl, }) {
|
|
150
181
|
try {
|
|
151
182
|
if (!publicKey)
|
|
@@ -181,7 +212,10 @@ async function handleSolanaRedeem({ provider, connection, vaultProgramId, vaultA
|
|
|
181
212
|
? new web3_js_1.PublicKey(vaultAddress)
|
|
182
213
|
: utils_1.SolanaUtils.deriveVaultStatePda(_vaultProgramId);
|
|
183
214
|
const vaultTokenAtaPda = utils_1.SolanaUtils.deriveVaultTokenAtaPda(_vaultProgramId, _depositMint, vaultVersion);
|
|
215
|
+
// Use on-chain share mint from vault state instead of deriving a PDA,
|
|
216
|
+
// since PDA derivation assumes one share mint per program (single-vault only).
|
|
184
217
|
const shareMintAddr = new web3_js_1.PublicKey(shareMint);
|
|
218
|
+
// Get share mint info to handle decimals
|
|
185
219
|
const shareMintInfo = await connection.getParsedAccountInfo(shareMintAddr);
|
|
186
220
|
if (!shareMintInfo.value) {
|
|
187
221
|
throw new Error('Could not fetch share mint info');
|
|
@@ -201,6 +235,7 @@ async function handleSolanaRedeem({ provider, connection, vaultProgramId, vaultA
|
|
|
201
235
|
}
|
|
202
236
|
redeemSharesRaw = (0, utils_1.uiAmountToRawBn)(redeemShares, shareDecimals);
|
|
203
237
|
}
|
|
238
|
+
// Find user's token accounts
|
|
204
239
|
const userTokenAccounts = await connection.getParsedTokenAccountsByOwner(_publicKey, {
|
|
205
240
|
mint: _depositMint,
|
|
206
241
|
});
|
|
@@ -215,6 +250,7 @@ async function handleSolanaRedeem({ provider, connection, vaultProgramId, vaultA
|
|
|
215
250
|
}
|
|
216
251
|
const senderTokenAccount = userTokenAccounts?.value[0]?.pubkey;
|
|
217
252
|
const senderShareAccount = userShareAccounts?.value[0]?.pubkey;
|
|
253
|
+
// Get the fee recipient from vault state
|
|
218
254
|
const readOnlyProvider = utils_1.SolanaUtils.getReadOnlyProvider({ connection });
|
|
219
255
|
const readOnlyProgram = utils_1.SolanaUtils.getProgram({
|
|
220
256
|
provider: readOnlyProvider,
|
|
@@ -222,13 +258,19 @@ async function handleSolanaRedeem({ provider, connection, vaultProgramId, vaultA
|
|
|
222
258
|
programId: _vaultProgramId.toBase58(),
|
|
223
259
|
});
|
|
224
260
|
const vaultStateData = await readOnlyProgram.account.vaultState.fetch(vaultStatePda);
|
|
261
|
+
// Get the fee recipient's token account
|
|
225
262
|
const feeRecipientTokenAccount = await (0, spl_token_1.getAssociatedTokenAddress)(_depositMint, vaultStateData.feeRecipient);
|
|
263
|
+
// Check if the fee recipient token account exists, if not create it
|
|
226
264
|
const feeRecipientAccountInfo = await connection.getAccountInfo(feeRecipientTokenAccount);
|
|
227
265
|
if (!feeRecipientAccountInfo) {
|
|
228
|
-
const createFeeRecipientAtaIx = (0, spl_token_1.createAssociatedTokenAccountInstruction)(_publicKey,
|
|
266
|
+
const createFeeRecipientAtaIx = (0, spl_token_1.createAssociatedTokenAccountInstruction)(_publicKey, // payer (user pays for the account creation)
|
|
267
|
+
feeRecipientTokenAccount, // associated token account
|
|
268
|
+
vaultStateData.feeRecipient, // owner (the actual fee recipient)
|
|
269
|
+
_depositMint);
|
|
229
270
|
const createAccountTx = new web3_js_1.Transaction().add(createFeeRecipientAtaIx);
|
|
230
271
|
const createAccountSignature = await sendTransaction(createAccountTx, connection);
|
|
231
272
|
core_1.Logger.log.info('handleSolanaRedeem', 'Fee recipient token account created:', createAccountSignature);
|
|
273
|
+
// Wait a moment for the account to be created
|
|
232
274
|
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
233
275
|
}
|
|
234
276
|
else {
|
|
@@ -246,6 +288,7 @@ async function handleSolanaRedeem({ provider, connection, vaultProgramId, vaultA
|
|
|
246
288
|
core_1.Logger.log.info('handleSolanaRedeem', 'Share mint:', shareMintAddr.toBase58());
|
|
247
289
|
core_1.Logger.log.info('handleSolanaRedeem', 'Deposit mint:', _depositMint?.toBase58());
|
|
248
290
|
core_1.Logger.log.info('handleSolanaRedeem', 'Signer:', _publicKey.toBase58());
|
|
291
|
+
// Get a fresh blockhash to avoid "Blockhash not found" errors
|
|
249
292
|
const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash('confirmed');
|
|
250
293
|
const tx = await program.methods
|
|
251
294
|
.redeem(redeemSharesRaw)
|
|
@@ -254,7 +297,7 @@ async function handleSolanaRedeem({ provider, connection, vaultProgramId, vaultA
|
|
|
254
297
|
vaultDepositAta: vaultTokenAtaPda,
|
|
255
298
|
senderTokenAccount,
|
|
256
299
|
senderShareAccount,
|
|
257
|
-
feeRecipientAccount: feeRecipientTokenAccount,
|
|
300
|
+
feeRecipientAccount: feeRecipientTokenAccount, // The actual fee recipient's token account
|
|
258
301
|
shareMint: shareMintAddr,
|
|
259
302
|
depositMint: _depositMint,
|
|
260
303
|
signer: _publicKey,
|
|
@@ -265,6 +308,7 @@ async function handleSolanaRedeem({ provider, connection, vaultProgramId, vaultA
|
|
|
265
308
|
preflightCommitment: 'confirmed',
|
|
266
309
|
});
|
|
267
310
|
core_1.Logger.log.info('handleSolanaRedeem', 'Redeem successful:', tx);
|
|
311
|
+
// Wait for confirmation with the blockhash we used
|
|
268
312
|
await connection.confirmTransaction({
|
|
269
313
|
signature: tx,
|
|
270
314
|
blockhash,
|
|
@@ -1,3 +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
|
+
*/
|
|
1
7
|
import { 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
|
+
*/
|
|
2
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
|
+
*/
|
|
3
28
|
export declare function handleStellarRedeem(params: IStellarRedeemParams): Promise<string>;
|
|
@@ -1,4 +1,10 @@
|
|
|
1
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
|
+
*/
|
|
2
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
9
|
exports.handleStellarDeposit = handleStellarDeposit;
|
|
4
10
|
exports.handleStellarRedeem = handleStellarRedeem;
|
|
@@ -16,6 +22,14 @@ function validateAccountAddress(address, label) {
|
|
|
16
22
|
throw new core_1.AugustValidationError('INVALID_ADDRESS', `Invalid ${label} address: expected a Stellar account (G-prefix), got "${address}"`);
|
|
17
23
|
}
|
|
18
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
|
+
*/
|
|
19
33
|
function buildSelfOperationArgs(amount, userAddress) {
|
|
20
34
|
const userScVal = new stellar_sdk_1.Address(userAddress).toScVal();
|
|
21
35
|
return [
|
|
@@ -25,6 +39,16 @@ function buildSelfOperationArgs(amount, userAddress) {
|
|
|
25
39
|
userScVal,
|
|
26
40
|
];
|
|
27
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
|
+
*/
|
|
28
52
|
async function handleStellarDeposit(params) {
|
|
29
53
|
const { contractId, amount, senderAddress, network } = params;
|
|
30
54
|
validateContractAddress(contractId);
|
|
@@ -33,6 +57,15 @@ async function handleStellarDeposit(params) {
|
|
|
33
57
|
const args = buildSelfOperationArgs((0, soroban_1.toBigIntAmount)(amount, 'deposit amount'), senderAddress);
|
|
34
58
|
return (0, soroban_1.buildSorobanTx)(config, senderAddress, contractId, 'deposit', args);
|
|
35
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
|
+
*/
|
|
36
69
|
async function handleStellarRedeem(params) {
|
|
37
70
|
const { contractId, shares, receiverAddress, network } = params;
|
|
38
71
|
validateContractAddress(contractId);
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stellar Constants
|
|
3
|
+
*/
|
|
1
4
|
import type { IStellarNetwork } from './types';
|
|
2
5
|
export declare const STELLAR_CHAIN_ID: number;
|
|
3
6
|
export declare const STELLAR_CHAIN: {
|
|
@@ -8,10 +11,33 @@ export declare const STELLAR_CHAIN: {
|
|
|
8
11
|
export declare const SOROBAN_RPC_URLS: Record<IStellarNetwork, string>;
|
|
9
12
|
export declare const NETWORK_PASSPHRASES: Record<IStellarNetwork, string>;
|
|
10
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
|
+
*/
|
|
11
28
|
export declare const TX_TIMEOUT_SECONDS = 600;
|
|
29
|
+
/** Timeout for read-only Soroban simulation queries (seconds). */
|
|
12
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
|
+
*/
|
|
13
35
|
export declare const MAX_FEE_STROOPS = "1000000";
|
|
36
|
+
/** Initial confirmation-poll interval (ms). Grows up to {@link POLL_INTERVAL_MAX_MS}. */
|
|
14
37
|
export declare const POLL_INTERVAL_MS = 2000;
|
|
38
|
+
/** Cap for the backed-off confirmation-poll interval (ms). */
|
|
15
39
|
export declare const POLL_INTERVAL_MAX_MS = 8000;
|
|
40
|
+
/** Multiplier applied to the poll interval after each NOT_FOUND poll. */
|
|
16
41
|
export declare const POLL_INTERVAL_BACKOFF = 1.5;
|
|
42
|
+
/** Maximum number of polling attempts before timeout. */
|
|
17
43
|
export declare const MAX_POLL_ATTEMPTS = 30;
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Stellar Constants
|
|
4
|
+
*/
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
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;
|
|
4
7
|
const stellar_sdk_1 = require("@stellar/stellar-sdk");
|
|
5
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.
|
|
6
10
|
exports.STELLAR_CHAIN_ID = web3_1.SPECIAL_CHAINS.stellar.chainId;
|
|
7
11
|
exports.STELLAR_CHAIN = web3_1.SPECIAL_CHAINS.stellar;
|
|
8
12
|
exports.SOROBAN_RPC_URLS = {
|
|
@@ -13,12 +17,37 @@ exports.NETWORK_PASSPHRASES = {
|
|
|
13
17
|
mainnet: stellar_sdk_1.Networks.PUBLIC,
|
|
14
18
|
testnet: stellar_sdk_1.Networks.TESTNET,
|
|
15
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.
|
|
16
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
|
+
*/
|
|
17
37
|
exports.TX_TIMEOUT_SECONDS = 600;
|
|
38
|
+
/** Timeout for read-only Soroban simulation queries (seconds). */
|
|
18
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
|
+
*/
|
|
19
44
|
exports.MAX_FEE_STROOPS = '1000000';
|
|
45
|
+
/** Initial confirmation-poll interval (ms). Grows up to {@link POLL_INTERVAL_MAX_MS}. */
|
|
20
46
|
exports.POLL_INTERVAL_MS = 2000;
|
|
47
|
+
/** Cap for the backed-off confirmation-poll interval (ms). */
|
|
21
48
|
exports.POLL_INTERVAL_MAX_MS = 8000;
|
|
49
|
+
/** Multiplier applied to the poll interval after each NOT_FOUND poll. */
|
|
22
50
|
exports.POLL_INTERVAL_BACKOFF = 1.5;
|
|
51
|
+
/** Maximum number of polling attempts before timeout. */
|
|
23
52
|
exports.MAX_POLL_ATTEMPTS = 30;
|
|
24
53
|
//# sourceMappingURL=constants.js.map
|
|
@@ -1,6 +1,62 @@
|
|
|
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
|
+
*/
|
|
1
10
|
import type { ITokenizedVault, IVault } from '../../types';
|
|
2
11
|
import type { IVaultBaseOptions } from '../../modules/vaults/types';
|
|
3
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
|
+
*/
|
|
4
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
|
+
* @returns The position, or `null` if the balance read failed or was unparseable.
|
|
41
|
+
* @throws AugustValidationError on an invalid `walletAddress`.
|
|
42
|
+
* @example
|
|
43
|
+
* ```ts
|
|
44
|
+
* const pos = await getStellarUserPosition(vault, wallet, 'mainnet');
|
|
45
|
+
* if (!pos || pos.decimalsFromFallback) {
|
|
46
|
+
* // Refuse to size a redeem — share scale is not authoritatively known.
|
|
47
|
+
* throw new Error('Stellar share decimals unresolved');
|
|
48
|
+
* }
|
|
49
|
+
* const human = Number(pos.shares) / 10 ** pos.decimals;
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
5
52
|
export declare const getStellarUserPosition: (vaultAddress: string, walletAddress: string, network?: IStellarNetwork) => Promise<IStellarUserPosition | null>;
|
|
53
|
+
/**
|
|
54
|
+
* Query the vault's `convert_to_shares` to preview how many shares a deposit
|
|
55
|
+
* amount would yield. Returns the raw share amount as a string, or null on
|
|
56
|
+
* failure.
|
|
57
|
+
*
|
|
58
|
+
* @param vaultAddress Stellar contract ID (C… address)
|
|
59
|
+
* @param rawAmount Deposit amount in the deposit token's smallest unit
|
|
60
|
+
* @param network 'mainnet' | 'testnet'
|
|
61
|
+
*/
|
|
6
62
|
export declare const convertToShares: (vaultAddress: string, rawAmount: string, network?: IStellarNetwork) => Promise<string | null>;
|
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Stellar Vault Getters
|
|
4
|
+
*
|
|
5
|
+
* Data fetching for Stellar vaults. Enriches backend metadata with on-chain
|
|
6
|
+
* total assets, total supply, and share decimals from Soroban RPC. Also
|
|
7
|
+
* provides user position queries and deposit preview (convertToShares).
|
|
8
|
+
* Falls back to backend TVL for total assets, zero for total supply, and
|
|
9
|
+
* STELLAR_FALLBACK_DECIMALS for share decimals when on-chain queries fail.
|
|
10
|
+
*/
|
|
2
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
12
|
exports.convertToShares = exports.getStellarUserPosition = exports.getStellarVault = void 0;
|
|
4
13
|
const stellar_sdk_1 = require("@stellar/stellar-sdk");
|
|
@@ -6,6 +15,16 @@ const core_1 = require("../../core");
|
|
|
6
15
|
const utils_1 = require("../../modules/vaults/utils");
|
|
7
16
|
const constants_1 = require("./constants");
|
|
8
17
|
const soroban_1 = require("./soroban");
|
|
18
|
+
/**
|
|
19
|
+
* Parse an ScVal into a share-decimals value, reporting whether the
|
|
20
|
+
* authoritative on-chain value was available.
|
|
21
|
+
*
|
|
22
|
+
* Returns `{ decimals, fromFallback }`. When the `decimals()` retval is missing
|
|
23
|
+
* or unparseable, `decimals` is STELLAR_FALLBACK_DECIMALS (7) and `fromFallback`
|
|
24
|
+
* is `true` — the signal callers need to avoid trusting a fabricated scale (a
|
|
25
|
+
* silent 7 under-redeems ERC4626 offset vaults; see AUGUST-6381). A successful
|
|
26
|
+
* parse returns the on-chain value with `fromFallback: false`.
|
|
27
|
+
*/
|
|
9
28
|
function parseDecimals(scVal, context, vaultAddress) {
|
|
10
29
|
if (!scVal) {
|
|
11
30
|
core_1.Logger.log.error(context, 'Decimals not available — using fallback (financial values may be incorrect)', {
|
|
@@ -26,9 +45,19 @@ function parseDecimals(scVal, context, vaultAddress) {
|
|
|
26
45
|
return { decimals: constants_1.STELLAR_FALLBACK_DECIMALS, fromFallback: true };
|
|
27
46
|
}
|
|
28
47
|
}
|
|
48
|
+
/**
|
|
49
|
+
* Parse an ScVal into a decimals number, returning the fallback on failure.
|
|
50
|
+
* Thin wrapper over {@link parseDecimals} for callers that only need the value
|
|
51
|
+
* (the fallback is already surfaced via logs). Prefer `parseDecimals` when the
|
|
52
|
+
* caller must distinguish a fallback from an authoritative read.
|
|
53
|
+
*/
|
|
29
54
|
function parseDecimalsOrFallback(scVal, context, vaultAddress) {
|
|
30
55
|
return parseDecimals(scVal, context, vaultAddress).decimals;
|
|
31
56
|
}
|
|
57
|
+
/**
|
|
58
|
+
* Resolve the Stellar network for a vault from its backend metadata.
|
|
59
|
+
* Logs a warning when falling back to mainnet.
|
|
60
|
+
*/
|
|
32
61
|
function resolveNetwork(tokenizedVault) {
|
|
33
62
|
const meta = tokenizedVault.stellar_vault_metadata;
|
|
34
63
|
const networkName = meta?.network_name;
|
|
@@ -43,6 +72,12 @@ function resolveNetwork(tokenizedVault) {
|
|
|
43
72
|
}
|
|
44
73
|
return 'mainnet';
|
|
45
74
|
}
|
|
75
|
+
/**
|
|
76
|
+
* Build a unified IVault from backend + on-chain data for Stellar vaults.
|
|
77
|
+
* Reads total assets and total supply from the Soroban contract via RPC.
|
|
78
|
+
* Falls back to backend `latest_reported_tvl` for total assets, or zero
|
|
79
|
+
* for total supply, when on-chain queries fail.
|
|
80
|
+
*/
|
|
46
81
|
const getStellarVault = async (tokenizedVault, _options) => {
|
|
47
82
|
const stellarMetadata = tokenizedVault.stellar_vault_metadata;
|
|
48
83
|
const depositDecimals = stellarMetadata?.deposit_token_decimals ?? constants_1.STELLAR_FALLBACK_DECIMALS;
|
|
@@ -53,6 +88,7 @@ const getStellarVault = async (tokenizedVault, _options) => {
|
|
|
53
88
|
STELLAR_FALLBACK_DECIMALS: constants_1.STELLAR_FALLBACK_DECIMALS,
|
|
54
89
|
});
|
|
55
90
|
}
|
|
91
|
+
// Attempt on-chain queries for total assets, total supply, and share decimals
|
|
56
92
|
const network = resolveNetwork(tokenizedVault);
|
|
57
93
|
const config = (0, soroban_1.resolveNetworkConfig)(network);
|
|
58
94
|
const [assetsResult, supplyResult, decimalsResult] = await Promise.all([
|
|
@@ -60,6 +96,7 @@ const getStellarVault = async (tokenizedVault, _options) => {
|
|
|
60
96
|
(0, soroban_1.queryContract)(config, tokenizedVault.address, 'total_supply'),
|
|
61
97
|
(0, soroban_1.queryContract)(config, tokenizedVault.address, 'decimals'),
|
|
62
98
|
]);
|
|
99
|
+
// Share token decimals may differ from deposit token decimals
|
|
63
100
|
const shareDecimals = parseDecimalsOrFallback(decimalsResult, 'getStellarVault', tokenizedVault.address);
|
|
64
101
|
let totalAssets;
|
|
65
102
|
if (assetsResult) {
|
|
@@ -114,8 +151,41 @@ const getStellarVault = async (tokenizedVault, _options) => {
|
|
|
114
151
|
});
|
|
115
152
|
};
|
|
116
153
|
exports.getStellarVault = getStellarVault;
|
|
154
|
+
/**
|
|
155
|
+
* Get user position for a Stellar vault.
|
|
156
|
+
* Queries the vault contract's balance(address) and decimals() functions via Soroban RPC.
|
|
157
|
+
*
|
|
158
|
+
* Returns `{ shares, decimals, decimalsFromFallback }` on success (shares may be
|
|
159
|
+
* '0' for zero balance), or null when the balance query fails. The two reads are
|
|
160
|
+
* independent: a `decimals()` failure does NOT null the result — instead
|
|
161
|
+
* `decimals` falls back to STELLAR_FALLBACK_DECIMALS (7) and
|
|
162
|
+
* `decimalsFromFallback` is set to `true` so callers can tell a fabricated 7
|
|
163
|
+
* apart from a genuine 7-decimal vault.
|
|
164
|
+
*
|
|
165
|
+
* Why this matters: an ERC4626 offset vault has share decimals = asset + offset
|
|
166
|
+
* (e.g. 13). A consumer that sizes a redeem trusting a silent fallback 7 would
|
|
167
|
+
* under-redeem by `10^offset`. Callers that settle a redeem from this position
|
|
168
|
+
* MUST refuse (surface an error) when `decimalsFromFallback` is `true` rather
|
|
169
|
+
* than trusting `decimals`. See AUGUST-6381 (follow-up to AUGUST-6380).
|
|
170
|
+
*
|
|
171
|
+
* @param vaultAddress - Stellar vault contract ID (C… address)
|
|
172
|
+
* @param walletAddress - User's Stellar account (G… address); validated upfront
|
|
173
|
+
* @param network - 'mainnet' | 'testnet' (defaults to 'mainnet')
|
|
174
|
+
* @returns The position, or `null` if the balance read failed or was unparseable.
|
|
175
|
+
* @throws AugustValidationError on an invalid `walletAddress`.
|
|
176
|
+
* @example
|
|
177
|
+
* ```ts
|
|
178
|
+
* const pos = await getStellarUserPosition(vault, wallet, 'mainnet');
|
|
179
|
+
* if (!pos || pos.decimalsFromFallback) {
|
|
180
|
+
* // Refuse to size a redeem — share scale is not authoritatively known.
|
|
181
|
+
* throw new Error('Stellar share decimals unresolved');
|
|
182
|
+
* }
|
|
183
|
+
* const human = Number(pos.shares) / 10 ** pos.decimals;
|
|
184
|
+
* ```
|
|
185
|
+
*/
|
|
117
186
|
const getStellarUserPosition = async (vaultAddress, walletAddress, network = 'mainnet') => {
|
|
118
187
|
const config = (0, soroban_1.resolveNetworkConfig)(network);
|
|
188
|
+
// Validate address upfront — invalid input is a caller bug, not an RPC issue
|
|
119
189
|
let userAddress;
|
|
120
190
|
try {
|
|
121
191
|
userAddress = new stellar_sdk_1.Address(walletAddress);
|
|
@@ -124,6 +194,7 @@ const getStellarUserPosition = async (vaultAddress, walletAddress, network = 'ma
|
|
|
124
194
|
throw new core_1.AugustValidationError('INVALID_ADDRESS', `getStellarUserPosition: invalid walletAddress "${walletAddress}": ${String(addrErr)}`, { cause: addrErr });
|
|
125
195
|
}
|
|
126
196
|
try {
|
|
197
|
+
// Fetch balance and decimals in parallel — they're independent queries
|
|
127
198
|
const [balanceResult, decimalsResult] = await Promise.all([
|
|
128
199
|
(0, soroban_1.queryContract)(config, vaultAddress, 'balance', [userAddress.toScVal()]),
|
|
129
200
|
(0, soroban_1.queryContract)(config, vaultAddress, 'decimals'),
|
|
@@ -164,7 +235,17 @@ const getStellarUserPosition = async (vaultAddress, walletAddress, network = 'ma
|
|
|
164
235
|
}
|
|
165
236
|
};
|
|
166
237
|
exports.getStellarUserPosition = getStellarUserPosition;
|
|
238
|
+
/**
|
|
239
|
+
* Query the vault's `convert_to_shares` to preview how many shares a deposit
|
|
240
|
+
* amount would yield. Returns the raw share amount as a string, or null on
|
|
241
|
+
* failure.
|
|
242
|
+
*
|
|
243
|
+
* @param vaultAddress Stellar contract ID (C… address)
|
|
244
|
+
* @param rawAmount Deposit amount in the deposit token's smallest unit
|
|
245
|
+
* @param network 'mainnet' | 'testnet'
|
|
246
|
+
*/
|
|
167
247
|
const convertToShares = async (vaultAddress, rawAmount, network = 'mainnet') => {
|
|
248
|
+
// Validate address upfront — invalid input is a caller bug, not an RPC issue
|
|
168
249
|
try {
|
|
169
250
|
new stellar_sdk_1.Address(vaultAddress);
|
|
170
251
|
}
|
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stellar Adapter for August SDK
|
|
3
|
+
*
|
|
4
|
+
* Provides Stellar vault operations: deposit, redeem, position queries,
|
|
5
|
+
* and on-chain data fetching via Soroban RPC.
|
|
6
|
+
*
|
|
7
|
+
* @module StellarAdapter
|
|
8
|
+
*/
|
|
1
9
|
import * as StellarConstants from './constants';
|
|
2
10
|
import * as StellarGetters from './getters';
|
|
3
11
|
import * as StellarActions from './actions';
|
|
@@ -14,16 +22,56 @@ export declare const Stellar: {
|
|
|
14
22
|
submit: typeof StellarSubmit;
|
|
15
23
|
getters: typeof StellarGetters;
|
|
16
24
|
};
|
|
25
|
+
/**
|
|
26
|
+
* Stellar Adapter for August SDK
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```
|
|
30
|
+
* const adapter = new StellarAdapter('testnet');
|
|
31
|
+
* const xdr = await adapter.vaultDeposit({
|
|
32
|
+
* contractId: 'CBGWW5...',
|
|
33
|
+
* amount: '1000000',
|
|
34
|
+
* senderAddress: 'GDLZ...',
|
|
35
|
+
* });
|
|
36
|
+
* // Sign xdr with wallet (e.g. Freighter), then submit via adapter.submitTransaction()
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
17
39
|
declare class StellarAdapter {
|
|
18
40
|
private _network;
|
|
19
41
|
constructor(network?: IStellarNetwork);
|
|
20
42
|
get network(): IStellarNetwork;
|
|
21
43
|
isStellarAddress(address: string): boolean;
|
|
22
44
|
getExplorerLink(id: string, type?: 'contract' | 'account' | 'tx'): string;
|
|
45
|
+
/**
|
|
46
|
+
* Build an unsigned deposit transaction for a Stellar vault.
|
|
47
|
+
* @returns Base64-encoded XDR of the unsigned transaction.
|
|
48
|
+
*/
|
|
23
49
|
vaultDeposit(params: Omit<IStellarDepositParams, 'network'>): Promise<string>;
|
|
50
|
+
/**
|
|
51
|
+
* Build an unsigned redeem transaction for a Stellar vault.
|
|
52
|
+
* @returns Base64-encoded XDR of the unsigned transaction.
|
|
53
|
+
*/
|
|
24
54
|
vaultRedeem(params: Omit<IStellarRedeemParams, 'network'>): Promise<string>;
|
|
55
|
+
/**
|
|
56
|
+
* Submit a signed Soroban transaction and poll until confirmed.
|
|
57
|
+
* @returns Transaction hash on success
|
|
58
|
+
*/
|
|
25
59
|
submitTransaction(signedXdr: string): Promise<string>;
|
|
60
|
+
/**
|
|
61
|
+
* Get user's vault share balance.
|
|
62
|
+
*
|
|
63
|
+
* @returns The position `{ shares, decimals, decimalsFromFallback }`, or null
|
|
64
|
+
* if the balance read fails. When `decimalsFromFallback` is `true` the
|
|
65
|
+
* `decimals()` read failed and `decimals` is the fallback (7) — callers sizing
|
|
66
|
+
* a redeem MUST refuse rather than trust it (see AUGUST-6381).
|
|
67
|
+
*/
|
|
26
68
|
getUserPosition(vaultAddress: string, walletAddress: string): Promise<IStellarUserPosition | null>;
|
|
69
|
+
/**
|
|
70
|
+
* Preview how many vault shares a deposit amount would yield.
|
|
71
|
+
* @param vaultAddress Stellar contract ID (C… address)
|
|
72
|
+
* @param rawAmount Deposit amount in the deposit token's smallest unit
|
|
73
|
+
* @returns Raw share amount as a string, or null if query fails.
|
|
74
|
+
*/
|
|
27
75
|
convertToShares(vaultAddress: string, rawAmount: string): Promise<string | null>;
|
|
28
76
|
}
|
|
29
77
|
export default StellarAdapter;
|