Changelog
9.6.0
Integrator highlights
Breaking: getVaultUserLifetimePnl now throws AugustPriceUnavailableError when USD price is unavailable, instead of returning $1-priced fields.
Action: Catch and handle AugustPriceUnavailableError when calling getVaultUserLifetimePnl to avoid displaying incorrect USD values.
Action: Stop using deprecated WEBSERVER_ENDPOINTS constants (default.hello, subaccount.rewards, subaccount.batch) before next major release.
Action: Update code that relied on global api.last_endpoint, api.server, and active.chainId scope tags; migrate to per-call breadcrumb data.
New: fetchAugustWithKey, fetchAugustPublic, and fetchAugustWithBearer now send x-august-app and x-august-sdk-version headers by default.
Full changelog
Minor Changes
41c558d: Identify the calling application on every backend request
fetchAugustWithKey,fetchAugustPublic, andfetchAugustWithBearernow sendx-august-app: <appName>andx-august-sdk-versionby default. TheAugustSDKconstructor wires its validatedappNamein through the newsetSdkAppName(process-global, last instance wins, likesetPublicApiBaseUrl). This gives the backend per-integrator request counts independent of Sentry sampling. Callers can still override either header per request.b307d78: feat:
getVaultUserLifetimePnlthrowsAugustPriceUnavailableError(codePRICE_UNAVAILABLE) instead of pricing the position at $1 per assetWhen the price server had no USD price for a vault's underlying asset — a failed lookup, a token it does not know, or an unreadable
asset()— the getter logged a warning and multiplied every USD field by1. For a non-dollar vault (lsETH, tETH, BTC) that reportedcurrentPositionValueUsd,totalDepositedUsd,totalWithdrawnUsdandlifetimePnlUsdin raw asset units, labelled as dollars: a ~$40k lsETH position read as ~$13, and nothing in the result showed it was wrong.The getter now throws the new typed
AugustPriceUnavailableErrorin that case, alongside the existingAugustHistoryUnavailableError:try { const pnl = await sdk.getVaultUserLifetimePnl({ vault, wallet, chainId }); } catch (err) { if (err instanceof AugustPriceUnavailableError) hideUsd(); else throw err; }Consumer impact: a call that previously resolved with $1-priced USD fields now rejects.
IVaultUserLifetimePnlis unchanged, and calls with a resolvable price return exactly what they did before. The failure is also logged at error level (it was a warning), so a missing price now surfaces as an SDK Sentry issue.d49c433: feat: add
isNativeSwapRouterDepositSupported(chainId, vault, options)— a read-only, provider-agnostic check for whether a vault accepts a native-ETH SwapRouter deposit (a SwapRouter is deployed on the chain, the vault is registered on it with the wrapped-native token as its reference asset, and the vault's ownasset()is that token). Two parallel RPC reads, no backend call. Lets a UI gate the native-ETH deposit option before offering it, instead of discovering unsupported vaults via a thrown error at deposit time. Also documents the wrap-only, WETH-vaults-only limitation of the on-chain SwapRouter onSWAP_ROUTER_WRAPPED_NATIVE,swapRouterDeposit, anddepositNativeViaSwapRouter.41c558d: Set
sdk.surfaceonce at init viaanalytics.surfacesdk.surfacewas only set insidecaptureSdkException, so errors reaching Sentry through the SDK's logger sink — the bulk of them — carried no surface at all.IAnalyticsConfiggains an optionalsurface('sdk'by default), whichinitializeSentryrecords as a sticky tag on every event and span. The CLI passes'cli';captureSdkExceptionaccepts'mcp'alongside the existing values.
Patch Changes
71642b3: Deprecate three
WEBSERVER_ENDPOINTSconstants pointing at routes that do not existdefault.hello,subaccount.rewards, andsubaccount.batchhave no backend handler and are never called by the SDK. They stay exported, marked@deprecated, so consumers keep compiling; they are removed in the next major release.209ce6e:
trackApiCallandtrackNetworkSwitchno longer set the globalapi.last_endpoint,api.server, andactive.chainIdscope tags. These stamped unrelated later events with stale values; the same data stays on each call's breadcrumb.41c558d: Correct analytics documentation that described behaviour the code no longer has
IAnalyticsConfig.tracesSampleRatedocuments its real default (0.1), the analytics module header no longer advertises cache monitoring, and theappNamevalidation error links to an "App name" section that now exists in the quick-start guide.41c558d: Tag first-party applications
partner.tier: internalupshift-web-app,upshift-earn,upshift-prime,august-cli, andaugust-mcpnow reportpartner.tier: internal, sopartner.tier:unverifiedin Sentry means "external integrator" today, without waiting for the backend verification endpoint.partner.idis unchanged.c685d31: fix: telemetry bug pass.
hashApiKeynow returns a real SHA-256 hash (was a last-5-characters mask), caches per key instead of returning the first key's value forever, and returns''instead of throwing whencrypto.createHashis unavailable (e.g. a browser bundle without acryptoshim), so the Sentry user is still set.getUserIdprecedence is nowapikey > wallet > domain > fingerprint > session(previouslydomainoutranked every identifier). Sync method tracking no longer sets the racy globalsdk.category/sdk.chaintags, and thebeforeSendTransactionnetwork sub-sampling is removed: the network methods are synchronous and create no transactions, so the filter only ever matched through that leaked tag and dropped ~90% of the unrelated transactions that followed aswitchNetwork/updateWallet/clearWallet/setSignercall — expect higher SDK transaction counts in Sentry after upgrading.getCacheStats/resetCacheStatsare deprecated (they never recorded anything and always return zeros; removal is planned for the next major). AddstrackKeyVerificationand success/failure telemetry forverifyAugustKey.41c558d: Carry app and partner identity on every
sdk.methodspanapp.name,partner.id,partner.tier,sdk.runtime,sdk.surface, andaugust.sdk_versionwere set as Sentry scope tags, which reach only the root span of a trace. Childsdk.methodspans — 86% of span rows — carried no identity at all, so the partner-usage dashboard could not filter them by application. The resolved identity is now copied onto each span as attributes.41c558d: Close the
sdk.category: unknownbucketpreviewRwaRedemptionis now classifiedread.redemption, and the EVM adapter's internal signer helper is renamed_getSignerso the instrumenter skips it (TypeScriptprivatedoes not hide a method from the prototype walk). A new test walks every instrumented prototype and fails on any public method without aMETHOD_CATEGORIESentry, and on any stale entry.
9.5.0
Integrator highlights
New:
getVaultAllocationsexposure items now includepoolIdfrom DeBank to distinguish identical positions in the same protocol
Full changelog
Minor Changes
98b5303: feat:
getVaultAllocationsexposure items (exposurePerCategory.supplying/borrowing) now carrypoolId— the DeBankpool.idof the portfolio item they came from — so consumers can tell apart two positions in the same protocol holding the same token (e.g. two Curve LPs that both report a trUSD leg).
9.4.0
Integrator highlights
Action: Default request timeout reduced to 15s; override via
timeoutMsorsetSdkRequestTimeoutif needed.Action: Solana deposit/redeem now quote expected output and apply 50-bps slippage floor by default; pass
slippageBps: 0to restore old behavior.Action: Solana
minSharesOut/minAssetsOutmust bebigintin range0 .. 2^64-1or throwsAugustValidationError.New:
getVaultAllocationsaccepts optional pre-fetchedtokenizedVaultrow to reduce backend requests.New:
IVault.isDepositPausednow reflects on-chaindepositsPaused()state instead of deny list only.
Full changelog
Minor Changes
cf09fc2: feat:
getVaultAllocationsaccepts an optional pre-fetchedtokenizedVaultrow, andgetVault(allocations: true)hands it the row it already holds instead of letting the getter re-readGET /tokenized_vault/{address}. The row is only reused when it can carry the borrower list (loadSubaccountsnotfalse,.subaccounts/.eoa_operatorspresent), so a row that cannot is fetched in full as before. This removes one backend request per enriched vault wherever the two reads did not already share a cache entry:getVaultcalled withloadSnapshots: false, and the per-vault enrichment insidegetVaults, which reads rows from the list endpoint. Backward-compatible; the new parameter is optional.ab0f251:
IVault.isDepositPausednow reflects the vault's on-chaindepositsPaused()stateFor EVM vaults the flag was derived solely from a hardcoded deny list of vault addresses (
isBadVault) — no contract read at all — while its siblingisWithdrawalPausedhad always been read from the chain. A curator pausing deposits on-chain therefore left every consumer showing an enabled deposit action, and each attempt reverted withDepositsPausedatestimateGas. This happened in production: Nerona Dollar Yield Strategy (Fluent,0xeaB765200189909c806FD6e20eBb4E57D6703C82) was paused on 2026-09-08 and kept failing user deposits for a week.depositsPausedis now read alongsidewithdrawalsPausedin the existing v1 and v2 vault batches and mapped ontoisDepositPaused, OR'd with the deny list so the previous behavior is preserved:isDepositPaused: contractCalls.depositsPaused === true || isBadVault(address);Consumer impact: a vault that is paused on-chain now reports
isDepositPaused: truewhere it previously reportedfalse— UIs that gate the deposit CTA on this field will start blocking those vaults (the intended behavior). No API shape change;IPoolFunctionsgains'depositsPaused'.Deployments too old to expose
depositsPaused()revert the call; that read resolves tofalserather than failing the whole vault fetch. Only a contract revert is demoted that way — transport failures (rate limit, timeout, network blip) are re-thrown, so a flaky RPC cannot make a paused vault look open.a631a2c: Add
claimWithdrawal— an SDK wrapper for the EVM-2 queued-withdrawalclaim()callTokenized Vault V2 (EVM-2) vaults settle a queued
requestRedeemthrough a separateclaim(year, month, day, receiverAddr)call once the withdrawal epoch has elapsed. The SDK had no wrapper for this — integrators building against EVM-2 vaults had to hand-encode the call themselves.augustSdk.evm.claimWithdrawal({ target, wallet, year, month, day, receiver?, wait? })wraps it directly, validates the vault is EVM-2, and returns the claim transaction hash. v1/v0 vaults keep using the existingvaultRedeemwrapper.year/month/daymust be non-negative integers (AugustValidationErrorotherwise), andwalletis the defaultreceiverof the withdrawn assets.a631a2c: Add SDK wrappers for EVM-2 vault-mechanics and queued-withdrawal reads
Integrators building directly against Tokenized Vault V2 (EVM-2) contracts had to hand-encode several reads the SDK didn't wrap, forcing them to maintain their own ABI slice for values the SDK already resolves internally. Six new
augustSdk.evm.*methods close that gap:getIdleLiquidity({ vault })—getTotalAssets() - externalAssets(), the balance available to an instant redemption.lagDuration({ vault })— the queued-withdrawal delay, in seconds.getWithdrawalEpoch({ vault })— the vault's current withdrawal epoch, by named field (year/month/day/claimableEpoch) rather than a positional tuple.getBurnableAmountByReceiver({ vault, receiver, year, month, day })— what a receiver can currently claim for a withdrawal-epoch date.getRequirementByDate({ vault, year, month, day })— total shares required to settle a date's queue.getScheduledTransactionsByDate({ vault, year, month, day })— scheduled queued-withdrawal volume for a date.
All six are EVM-2 only and throw
AugustValidationErroragainst a v1/v0 vault rather than silently returning a wrong value. Theyear/month/dayinputs are validated up front: a non-integer or negative value throwsAugustValidationError('INVALID_INPUT')before any RPC.20a57d2: feat: honor
includeClosedon the single-vault path.AugustVaults.getVaultrebuilt itsIVaultBaseOptionsfrom scratch and dropped the caller'sincludeClosed, so the flag was reachable only via the pluralgetVaults. The per-vault EVM getters null out aclosed+is_visible: falsevault unless it is set, which meant reading ONE closed vault by address could never resolve it — no matter what the caller passed.includeClosedis now declared onIVaultCustomOptions(previously only onIVaultBaseOptions, whichgetVault'soptionsparameter does not accept) and forwarded through.This unblocks holder-facing surfaces that read a single vault by address: a position in a closed vault returned
null, which consumers dereferenced, leaving no in-app way to withdraw.c4e9dc2: Cut backend request timeouts: 15s default, de-duplicated vault fetches, cached and bounded subaccount enrichment
One integrator produced ~40k
AugustTimeoutErrorevents a week, arriving in bursts of 20–30 in the same second — a single server render fanning out to the same endpoints and stalling as a group. Four changes address that:Default request timeout is now 15s (was 90s), still overridable per call via
timeoutMsand process-wide viasetSdkRequestTimeout. 90s outlived every realistic caller: a server-rendered integration had been abandoned upstream long before the abort fired, while the socket stayed open holding backend capacity and deepening the stall for everyone else.fetchTokenizedVault/fetchTokenizedVaultsde-duplicate in-flight requests. The response cache only helped sequential callers; on a cold process every concurrentgetVaultfor the same vault hit the backend. They now join one request. Failures are not cached — the next caller retries.getVaultAllocationsmemoizes CeFi/OTC answers per borrower for 60s and fetches them through a bounded concurrency window instead of one sequential request per borrower. "No record" is memoized too (it is the common answer); genuine failures are not.Recovered failures are breadcrumbs, not issues. A fetcher timeout is still thrown to the caller — who alone knows whether it is fatal — but is no longer also logged at error level, and
getSymbolreports a failed read as a structured warning instead of an error whose message embedded the token address.
Behavior for callers is unchanged apart from the shorter default deadline: integrations that legitimately need longer should set
timeoutMsor callsetSdkRequestTimeout.984a21e: Solana
vaultDeposit/vaultRedeemnow senddeposit_checked/redeem_checkedwith a slippage floorBoth actions sent the program's unguarded
depositandredeem, so a share-price move between quote and execution was silently accepted. The program has shipped the checked variants since v0.1.1; the SDK now uses them.By default the SDK quotes the expected output from the vault's current state with the program's own share math (virtual-share offset, pro-rata floor/cap, withdrawal fee) and passes that quote lowered by 50 bps as the floor. A new trailing
optionsargument onsdk.solana.vaultDepositandsdk.solana.vaultRedeemacceptsslippageBpsor an explicitminSharesOut/minAssetsOut(raw units; the redeem floor is net of the withdrawal fee). Passing0nrestores the old unguarded behaviour.A deposit that would now revert with
SlippageExceeded(code 6018) surfaces a message saying the price moved past the tolerance and how to retry.An explicit
minSharesOut/minAssetsOutoutside0 .. 2^64-1(or not abigint) now throwsAugustValidationErrorbefore any RPC. Previously a negative floor reached Anchor's unsigned encoder, which writes aBN's magnitude and drops the sign, so-1nbecame an on-chain floor of1.RPC: vault state and share-mint supply are read in one
getMultipleAccountsInfo, so they always come from the same slot — read separately they could straddle someone else's deposit and price a supply against assets that never coexisted. The deposit path performs one additional read to build the quote, skipped whenminSharesOutis supplied; redeem performs one fewer than before, having folded its share-mint and vault-state reads into the same snapshot.
Patch Changes
a631a2c: Stop sending a redundant receipt-token approval before EVM-2
instantRedeemvaultRequestRedeemchecked the receipt (share) token's allowance to the vault and sent anapprovewhen it was short on both EVM-2 redeem paths. On the instant path this was wasted:instantRedeemburns the caller's own shares directly on the vault side rather than pulling them viatransferFrom, so there is nothing for an allowance to gate. Verified on a mainnet fork — aninstantRedeemsucceeds with a0receipt-token allowance and no precedingapprove.The queued path is unchanged.
requestRedeemescrows the shares in the vault viatransferFrom, so the vault must be approved as spender — without that approval the call reverts withERC20InsufficientAllowance. The SDK keeps sending the approval there whenever the allowance is short.Consumer impact: an instant redeem that previously sent an
approvetransaction beforeinstantRedeemnow sends only the redeem transaction. Queued redeems behave exactly as before. No API shape change.75a22c0: docs: TSDoc cleanup for the generated reference — describe
init()andAugustSDK.vaultDeposit()correctly, drop internal ticket ids and benchmark file paths from published comments, and replace the expired 2026-01-01 removal date on thehgETH*LiquidAPYdeprecations with "next major release".
9.3.0
Integrator highlights
Breaking: Position labelling now requires 99% asset coverage; multi-asset vaults no longer receive a single asset symbol.
Action: For multi-asset vaults, read
tokensfromgetVaultAllocationsinstead ofexposurePerCategoryfor per-asset breakdown.New:
untangledAssetExposurereturns vault-level token exposure composition.New:
getVaultAllocationsserves asset composition asIVaultAllocations.tokensfor Stellar vaults.
Full changelog
Minor Changes
cc05a6b: Surface a Stellar vault's asset composition, and stop labelling positions with an asset the report cannot support
Untangled decomposes a vault's TVL two ways — by venue (
byProtocol) and by asset (byAsset) — and publishes no join between them. The transform readbyAssetonly to pick a name, tagging every synthesized position with the single largest asset and discarding the rest. Gami earnUSDC is 84.18% USDC and 15.82% deJTRSY, so the breakdown reported all $25.3M of it as USDC and the $4.0M of deJTRSY appeared nowhere at all.untangledAssetExposurereturns the composition as vault-level token exposure, andgetVaultAllocationsserves it asIVaultAllocations.tokensfor Stellar vaults. Negative rows are kept: a vault holding a position in another Upshift vault is reported owing the asset it spent (earnXLM carriesearnUSDC +$1,170,913againstUSDC -$1,170,271), and the two only sum back totvlUsdtogether.A position is now labelled with the vault's asset only when that asset covers at least 99% of
tvlUsd— true of earnXLM (99.98% XLM), false of earnUSDC. Below that the token carries its value with no symbol rather than asserting a holding the report does not support; protocol totals, the wallet bucket andnetValueare unchanged. Consumers reading a per-venue asset split out ofexposurePerCategoryshould readtokensinstead for multi-asset vaults.
9.2.2
Integrator highlights — internal changes only; no integrator action needed.
Full changelog
Patch Changes
a724e5b: Group Sentry errors by a normalized signature instead of the raw message
The per-signature error rate limiter keyed on the first 120 characters of the raw message, but the variable part of a message is usually an address near the front (
Request timeout after 90s: /subaccount/0x3F13…/otc_positions). Every vault and wallet therefore got its own signature — its own private rate-limit allowance, and its own Sentry issue — so one backend timeout billed thousands of events across dozens of issues in a day.Addresses, query strings, and long digit runs are now masked before the signature is built, and outgoing events carry that signature as their Sentry fingerprint so the copies group into one issue. Distinct endpoints and failure modes stay separate; the full message and tags still carry the address.
a724e5b: Stop
getTokenfetching against an undefined Solana RPC endpointendpointis optional onISolanaConnectionOptions, so a caller with no Solana RPC configured reachedfetch(undefined, ...). The runtime's fetch wrapper threwCannot read properties of undefined (reading 'toString'), whichgetTokenswallowed intoLogger.log.error— an unactionable Sentry error on every server render of a Solana vault.getTokennow returnsnullbefore the request when no endpoint is configured. A genuine metadata fetch failure also logs at warn instead of error: callers fall back to backend metadata onnull, so the lookup failing is degraded-but-handled, not an error.a724e5b: Recover the Solana RPC endpoint from the connection in
getSolanaVaultgetSolanaVaultread its endpoint fromoptions.rpcUrl, which is resolved upstream asproviders[vault.chain]— a map keyed by EVM chain id. Solana's synthetic chain id is never in it, so the field arrivedundefinedfor every Solana vault regardless of how the consuming app had configured its Solana RPC, and the deposit-token metadata lookup fetched againstundefined.The connection built from that RPC is already passed as
solanaService, so the endpoint now falls back tosolanaService.connection.rpcEndpoint. An explicitoptions.rpcUrlstill wins.69ad798: Stop counting a Stellar vault's position in another Upshift vault as idle
Untangled's
upshiftprotocol slug is the vault's own idle buffer plus any receipt tokens it holds in another Upshift vault, andtransformUntangledToDebankwas filing all of it as wallet holdings. Gami earnXLM therefore showed$1.97Midle on a$3.71Mvault when only$797Kwas undeployed — the$1.17Mit has deposited into earnUSDC was invisible.The transform now sizes the buffer from the report's
idlelocation and emits the remainder as a realupshiftposition, named after the receipt token whosebyAssetvalue matches it. Vaults whoseupshiftslice is only the idle buffer (Gami earnUSDC) are unchanged, as are reports with noidlelocation. Naming abstains rather than guesses: if no asset matches the remainder, or more than one does, the slice keeps the genericUpshiftlabel — the USD value comes frombyProtocoleither way.
9.2.1
Integrator highlights
Action: Stellar vaults with
allocations: truenow incur one additional HTTP call to Untangled and populatedefiandexposurePerCategoryfields.
Full changelog
Patch Changes
c578d64: fix: let
getVault({ allocations: true })reach the Stellar exposure pathgetVaultAllocationsresolves Stellar vaults through the Untangled portfolio API, butgetVaultonly ran its loans/allocations enrichment when the vault was EVM — andstellar-0is excluded from that check. So the standalone getter returned real exposure while every consumer going throughgetVault(the composite the web apps call) received the empty default and fell back to a deployed/idle split with no indication anything was missing.The gate is now per-leg rather than one EVM-or-nothing branch: loans stay EVM-only, because there is no non-EVM loan book to read, and allocations additionally cover Stellar. Solana and Sui are unchanged — no vault-level portfolio provider covers them, so they keep the empty defaults on both legs and pay for no extra call.
No signature or return-shape change. Stellar callers that pass
allocations: truenow get one additional HTTP call (the Untangled requestgetVaultAllocationsalready documented) and a populateddefi/exposurePerCategory; every other chain family is byte-identical to before.
9.2.0
Integrator highlights
New:
getVaultAllocationsnow resolves Stellar vault exposure via Untangled portfolio API with no consumer code changes.New: Stellar vaults now return populated
defi,tokens, andexposurePerCategoryfields matching EVM behavior.
Full changelog
Minor Changes
55a6c32: feat: resolve Stellar vault exposure via Untangled portfolio API in
getVaultAllocationsStellar vaults returned an empty exposure breakdown because no portfolio provider covered them — DeBank and Octav.fi have no Stellar coverage, so the vault's capital was invisible even though its TVL was not.
getVaultAllocationsnow resolves Stellar vaults through the Untangled portfolio API, which reconciles the whole vault in one call: the idle buffer, Stellar protocol positions (Blend, Aquarius), custody wallet balances, and capital bridged to other chains (Templar on NEAR). The results populate the samedefi,tokensandexposurePerCategoryfields EVM vaults already return, so consumers need no changes.Adds exactly one HTTP call for Stellar vaults and zero for every other chain. If the call fails, the exposure section comes back empty rather than throwing — the CeFi, OTC and loan allocations still resolve.
9.1.0
Integrator highlights
Action: Curator alerts enabled by default in production; opt out via
monitoring.curatorAlerts.enabledorAUGUST_SDK_DISABLE_CURATOR_ALERTS.Action: Sentry analytics localhost suppression expands to all RFC 1918 and private ranges; configure
monitoring.envif needed.Action: Browser deployments must allowlist curator API origin if curator alerts are enabled.
New: Stellar redemption failures now reported to August API for curator notification.
New: New
configureCuratorAlertsexport andICuratorAlertsContexttype for opt-out without SDK construction.
Full changelog
Minor Changes
e1f60ed: feat(stellar): notify vault curators when a redemption fails
Stellar vaults are instant-redeem only — there is no withdrawal queue — so a curator whose depositors cannot get out had no signal at all. Failed Stellar redemptions are now reported to the August API (the same base URL the SDK already reads vault data from, so a deployment pointed at staging reports to staging), which validates each report and forwards it to that vault's curator.
Two cases are reported: a redemption the vault cannot serve at build time — the contract rejected the call, or its ledger state needs restoring — and a submitted redeem whose operation ran and failed (
resultCode === 'txFailed'). The body carries which case it was, the network, the vault contract ID, the redeeming account, the unscaled share amount, a timestamp, the failure reason (secrets scrubbed, capped at 1500 characters), the consumer'sappName, and for the submitted case the transaction hash and result code. Repeat attempts at the same failure collapse to one report per 10 minutes.Not reported, because none of them reached the vault: invalid addresses, unfunded Stellar accounts, RPC outages, RPC-rejected broadcasts, confirmation timeouts, and transaction-level failures where the redeem never executed (
txBadSeq,txInsufficientBalance,txTooLate, or an undecodable result code). Deposits are never reported. Note that a redeem exhausting its Soroban resource budget is reported — the operation ran, so it arrives astxFailed.Enabled by default in production only: nothing is emitted unless
monitoring.envisPROD(which is the default whenmonitoringis omitted),NODE_ENVis neitherdevelopmentnortest, and — in a browser, where bundlers stripprocess.env— the page is not served from a loopback, private, or link-local host (localhost, the.localhostand.localnames,127.0.0.0/8,0.0.0.0/8, the RFC 1918 ranges,169.254.0.0/16, and the IPv6 equivalents including[::1]). Non-mainnet failures are dropped as well, unlesscuratorAlerts.endpointis set — pointing at your own relay lifts the mainnet-only restriction so a testnet integration can exercise the path. So a consumer's CI and local dev runs stay quiet by default. Opt out withmonitoring: { curatorAlerts: { enabled: false } }, with the newly exportedconfigureCuratorAlerts(for code that drives theStellarnamespace without constructing an SDK, and the only opt-out available in a browser;ICuratorAlertsContextis exported alongside it so a wrapper can be typed), or with theAUGUST_SDK_DISABLE_CURATOR_ALERTSenv var in Node. Code using theStellarnamespace directly has nomonitoring.env, soNODE_ENVand the serving hostname are its gates. Settingenabled: trueis a force-on that bypasses all of the environment gates — only the env var still overrides it.Reporting is fire-and-forget: it never delays, alters, or swallows the error the caller receives, and costs at most one extra POST on an already-failing call. Delivery to a browser depends on the API's CORS allowlist, so onboarding a curator also means allowlisting the origin their users load.
The report itself is chain-agnostic: it names its chain family and the receiving endpoint validates the identifiers by that family's rules, so a second chain is a server-side registry entry rather than a new endpoint. Only Stellar is served today — the other chains have a withdrawal queue and a different escalation path.
Sentry analytics is gated on the same, now-shared, internal helper, so its own localhost suppression widens identically — this is a behavior change for existing analytics consumers, independent of curator alerts. Browser sessions served from any of the hosts listed above now stop sending analytics where previously only the bare name
localhostand127.0.0.1were suppressed. In a browser this cannot be overridden: the force-on flag for analytics is read fromprocess.env, which a bundler strips, so a partner who deliberately wants analytics from a private-range origin (a LAN-hosted staging app, a container reached by IP) will silently get none. Node is unaffected — its own env override still applies.Also adds
context.stage('simulation','restore-required','assembly','rpc-failover') to the errors thrown while building a Soroban transaction, so callers can tell a vault-level rejection from a transport problem. Validation errors such asACCOUNT_NOT_FUNDEDcarry no stage.No
METHOD_CATEGORIESentry is needed: the new exports are free functions, not methods on an instrumented class.
9.0.0
Integrator highlights
Breaking:
initializeSentrysignature changed:appNamemoved from fifth optional to third required parameter.Breaking: EVM address strings (0x + 40 hex chars) now rejected as invalid
appNamevalues in constructor andinitializeSentry.Action: Direct
initializeSentrycallers must reorder: moveappNameto third position after config and environment.New: Typed validation errors:
appNamefailures throwAugustValidationErrorwith codeINVALID_INPUT.
Full changelog
Major Changes
192f289: feat!: require
appNameoninitializeSentry— no more anonymous telemetryBreaking —
initializeSentrysignature reordered. The standaloneinitializeSentryexport was the last entry point that could start SDK telemetry without an application identity, producingunverified:anonymousevents that are invisible on the partner-usage dashboard (theAugustSDKconstructor has requiredappNamesince v5). The signature is now:initializeSentry(config, environment, appName, walletAddress?, apiKey?)appNamemoved from the optional fifth parameter to the required third parameter and is validated with the same rules as the constructor (3–64 chars,[a-zA-Z0-9._-], slug not display name). Invalid or missing values throw synchronously, before the idempotency short-circuit and the environment gates, so the failure is equally loud everywhere.New validation rule (constructor +
initializeSentry): values shaped like an EVM address (0x+ 40 hex chars) are rejected. An address passes the character rules but is a wallet identifier, not an app name — and it is exactly what a pre-v9 caller still on the old positional order would now be passing in theappNameslot. The error message points at the reorder.Typed validation errors:
appNamevalidation failures (constructor andinitializeSentry) now throwAugustValidationErrorwith codeINVALID_INPUTinstead of a rawError. Messages are unchanged;instanceof Errorstill holds, so message-based handling keeps working.Migration: most integrators never call
initializeSentrydirectly — theAugustSDKconstructor calls it — and need no change. Direct callers moveappNameto the third position:initializeSentry({ enabled: true }, 'PROD', 'acme-trader').The CLI (
@augustdigital/cli) was updated to the new call shape; its behavior is unchanged (august-cliidentity, eager init).
8.26.0
Integrator highlights
Action: Call
getVaults()with optional chaining if passing no arguments to avoid TypeError.New: Export
IGetVaultsOptionstype for use withAugustSDK.getVaultsandAugustVaults.getVaults.New: New
maxRetriesandbaseDelayoptions ongetVaultsto tune retry backoff.New:
getVaultandgetIdleAssetsaccept optional pre-fetched data for efficiency.
Full changelog
Minor Changes
b84d902: feat: export
IGetVaultsOptionsand use it on bothAugustSDK.getVaultsandAugustVaults.getVaults. The facade previously declared a narrower inline options type that rejected documented options (includeClosed, and the newmaxRetries/baseDelayretry tuning) at compile time even though they were honored at runtime.
Patch Changes
073a2b3: fix(vaults):
getVaults()with no arguments no longer throws. The wallet-position gate readoptions.walletwithout optional chaining, so the documented no-options call crashed with a TypeError before returning the vault list.c0e22a4: perf(vaults): cut the getVaults list-path cost without changing its output
Skip per-vault enrichment for vaults the post-enrichment filter is guaranteed to drop (closed vaults without
includeClosed, unknown-status visible vaults). On chain-scoped sweeps this removes the majority of the slowest on-chain reads and their retry backoff; the returned set is unchanged.Re-use the backend list row inside each per-vault
getVaultcall instead of re-fetchingGET /tokenized_vault/{address}per vault (and once more insidegetIdleAssets), removing 2 backend requests per vault per sweep.Fetch Ember (Sui) vaults only when the caller's
chainIdsincludes the Sui chain, cache the Bluefin payload for 5 minutes, and abort the request after 5s — previously this uncached third-party call was awaited unconditionally with no timeout and could stall everygetVaultsconsumer indefinitely.Expose
maxRetries/baseDelayongetVaultsoptions so callers racing the sweep against their own budget can bound the per-vault retry backoff (defaults unchanged: 5 attempts, 2000ms base).getVaultaccepts an optional pre-fetchedtokenizedVaultrow andgetIdleAssetsan optional pre-resolved version (both backward-compatible).
8.25.0
Integrator highlights
Action: Use
deposit_checked/redeem_checkedfor slippage bounds in new Solana vault integrations.Action:
swapRouterDepositnow requires validoriginCodeor sends zero sentinel; omit it to use sentinel instead of malformed code.New: Nine new transparency dashboard read methods:
getVaultPositionSnapshot,getVaultBackingSeries,getVaultSmoothedApy,getVaultHistoricalAllocations,getVaultFeeConfig,getVaultGovernanceRoles,getVaultGovernancePermissions,getVaultGovernanceTimelocks,getVaultGovernanceAuditLog.New: Solana vault IDL refreshed with
deposit_checked,redeem_checked,initialize_config,set_config_authority,override_config_authorityinstructions andVaultState.share_offsetfield.
Full changelog
Minor Changes
64abba0: feat: refresh the Solana vault IDL to the deployed ProgramConfig build (AUGUST-7416)
The
august_vaultprogram was upgraded on mainnet on 2026-08-06 (devnetC8B1…a day earlier) and the committed IDL was never refreshed, sovault-idl.tsdescribed a January build. The two ELFs are the same source build — byte-diffing them yields 279 differing bytes, all of them the program id — but the interface had moved.Regenerated from the program repo artifact.
vault-idl.tsnow comes from solana-vaultsfrontend/idl/august_vault.json, not fromanchor idl fetch. An Anchor IDL upload is not refreshed by a program upgrade, so every IDL published for this program lineage is seven months stale:up12…on mainnet was last written 2026-01-21 and theC8B1…devnet reference 2026-01-23. The file header now says so.Added surface: instructions
deposit_checked,redeem_checked,initialize_config,set_config_authority,override_config_authority; accountProgramConfig; error codes 6016–6020; andVaultState.share_offset.deposit_checked/redeem_checkedare slippage-bounded variants ofdeposit/redeem— the program's own docs recommend them for new integrations.No behaviour change for existing call sites.
depositandredeemare byte-identical to the previous IDL, so every transaction the SDK builds is unchanged.share_offsetwas carved out ofVaultState.padding([u64;32]→[u64;31]), leaving the struct at 455 bytes with every pre-existing field at its original offset, so account decoding is unaffected. Theinitializeandoperator_*changes in the new build touch instructions the SDK never builds.Drift guard reworked. The structural fingerprint against
C8B1…'s published IDL was dead weight: it passed while the on-chain interface gained five instructions, because the oracle it compared against predates the build it serves. It is replaced by a check that every discriminator the committed IDL declares is present in the deployed executable, plus an offline check that each declared discriminator still matchessha256("<prefix>:<name>"). The binary pin and live-VaultState-decode checks are unchanged.Known follow-up (AUGUST-7416).
share_offsetis a virtual-share offset: the program prices deposits asamount * (supply + offset) / (total_assets + offset), where a stored0resolves toEXTRA_SHARES(1e6) rather than meaning "no offset".getSolanaVaultstill derives share price pro-rata fromlocal_aum + deployed_aumagainst share-mint supply, which agrees with the program only at par. This changeset does not alter that math — it needs confirmation from the contracts team first.RPC/latency: unchanged at runtime. The drift test makes one fewer IDL fetch and one extra ProgramData read.
0cddc4f: feat: expose the transparency dashboard through the SDK — nine new read methods on
sdk.apiModule, one per tab/card so partners can compose exactly the subset they want:getVaultPositionSnapshot,getVaultBackingSeries,getVaultSmoothedApy,getVaultHistoricalAllocations,getVaultFeeConfig,getVaultGovernanceRoles,getVaultGovernancePermissions,getVaultGovernanceTimelocks,getVaultGovernanceAuditLog. All public (no API key), one HTTPS request each, zero RPC. Also documents thatgetVaultAllocationsis the data source behind the Upshift "Vault Exposure" section (that call itself still needs an RPC provider, and an API key for its CeFi/OTC legs).
Patch Changes
2f2bea9: fix:
swapRouterDepositnow forwardsoriginCodeto the SwapRouterswapRouterDepositaccepted anoriginCodein its options type but dropped it before dispatch, so every deposit settled on the all-zero sentinel and a partner's origin fee was silently never accrued. The code is now threaded through all three router paths — direct reference-asset deposit, swap deposit, and native deposit. Omitting it still sends the sentinel ("no origin fee"), and a malformed code throwsAugustValidationErrorinstead of falling back.
8.24.0
Integrator highlights
Breaking: getAttributionSuffix(chainId?) now returns undefined when chains restriction is configured without chainId passed
Action: Pass chainId through to attribution methods if unattributed writes were relied upon with chains restriction set
New: isAttributionEnabled() exported to report attribution config presence independent of chain gate
New: approveCrossChain takes optional trailing chainId parameter to gate dataSuffix
Full changelog
Minor Changes
6e3caa0: fix: ERC-8021 attribution chain gate is fail-closed, unblocking Ledger approvals
attribution.chainsused to fail open: a write whose chain ID could not be determined got the suffix anyway, on the reasoning that over-attribution is harmless. It is not. The suffix makes calldata longer than the ABI encoding of the call, which breaks clear-signing on hardware wallets — a Ledger rejects an over-long ERC-20approvewithEthAppCommandError: Invalid data 6a80, so a user on an unattributed chain could not transact at all. Reported against a mainnet vault deposit from Rabby + Ledger Nano S.getAttributionSuffix(chainId?)returnsundefinedwhen achainsrestriction is configured and no chain ID is passed. Unrestricted attribution (nochains) is unchanged and still attributes every chain.wrapSignerWithAttributionsends the transaction unattributed when the provider network lookup fails, instead of appending blind. Its enabled check now uses the newisAttributionEnabled(), so the chain gate no longer turns the whole wrap into a pass-through.isAttributionEnabled()(new, exported) reports config presence independent of the chain gate.approveCrossChaintakes an optional trailingchainIdand gates itsdataSuffixon it; both call sites incrossChainVaultpass the chain they already resolve (props.userChainId,props.config.hubChainId). This was the one remaining write that appended the suffix with no chain check — and anapprove, the exact call Ledger refuses.
Integrators that set
attribution.chainsand rely on unknown-chain writes being attributed will now see those writes go out clean; pass the chain ID through if the attribution matters more than clear-signing.
8.23.0
Integrator highlights
Action: Set AUGUST_SDK_SLACK_WEBHOOK_URL environment variable or Slack alerts from subgraph readers will be disabled
Action: Migrate from deprecated DEFAULT_SLACK_WEBHOOK_URL and use resolveSlackWebhookUrl() instead
New: august.sdk_version Sentry tag added for querying consumer SDK build version
Full changelog
Minor Changes
b2a1376: fix: let consumers configure their own Slack webhook, and stop shipping August's
Every
slackWebookUrlparameter in the subgraph readers defaulted toDEFAULT_SLACK_WEBHOOK_URL, a hardcoded webhook path baked into the published bundle and the generated.d.ts. A Slack webhook path is a bearer credential, so this both exposed an internal August channel to anyone who installed the SDK and sent consumers' vault alerts to that channel with no way to redirect them.The webhook is now resolved at call time: an explicit argument wins, otherwise
AUGUST_SDK_SLACK_WEBHOOK_URLfrom the environment, otherwise alerting is disabled (a one-time console warning, rather than defaulting to somebody else's channel). Both the fullhttps://hooks.slack.com/services/…URL and the bareT…/B…/x…path are accepted.Action required for deployments that relied on the default: set
AUGUST_SDK_SLACK_WEBHOOK_URL, or Slack alerts from the subgraph readers will be silently disabled.DEFAULT_SLACK_WEBHOOK_URLis now''and deprecated; it is removed in the next major. UseresolveSlackWebhookUrl()instead.
Patch Changes
0ad9bd8: feat: add
august.sdk_versionSentry tag so a consumer's SDK build is queryablesdk.versionis a reserved Sentry field — Sentry populates it with the version of its own client, so querying it returned@sentry/core's version for every consumer rather than the August SDK's. The real value was only reachable astags[sdk.version].The same value is now also tagged as
august.sdk_version, which Sentry does not shadow.sdk.versionis still set for back-compat with existing saved queries, dashboards, and alert rules; it is deprecated and will be removed in the next major.82091ae: fix: retry rate-limited eth_getLogs chunks in getVaultRedemptionHistory and lower batch size to 8
7fc29b2: fix: stop the four highest-volume production error paths
getVaultAvailableRedemptionsno longer fails outright on vaults that do not implementlagDuration(). The emptyeth_callresponse is retried, then treated as "no claim lag" — previously it threw, which both raised an error per call and returned an empty redemption list for the affected vaults.getVaultRedemptionHistoryretrieseth_getLogschunks rejected by a provider rate limit, and lowers batch concurrency from 20 to 8. A transient cap used to abort the entire scan.getDecimalsrecords a transient transport fault as a breadcrumb rather than an error. Its contract is unchanged: it still never throws, still does not retry, and still resolvesundefinedon failure.CeFi/OTC subaccount enrichment treats a
400("borrower not tracked") like404/204— a breadcrumb.401and5xxstay error-level.
4c6ed05: fix: demote CeFi/OTC subaccount enrichment 400 to breadcrumb severity
8.21.1
Integrator highlights
New: X Layer (chain 196) is now registered with RPC endpoint and Multicall3 support
Full changelog
Patch Changes
de20993: feat: register X Layer (chain 196)
X Layer (OKX's Polygon-CDK zkEVM, native OKB, 18 decimals) joins the EVM chains the SDK understands:
NETWORKS[196]—X Layer, explorerhttps://xlayerscan.com. This is whatexplorerLinkuses for tx/address links, and whatchainIdToTagValueslugifies for thesdk.chainSentry tag (x-layerinstead ofunknown:196). It also lands the chain inAVAILABLE_CHAINS.FALLBACK_RPC_URLS[196]—https://rpc.xlayer.tech, used when a caller supplies no provider for the chain. Verified live on 2026-08-11: returnseth_chainId0xc4and sendsaccess-control-allow-origin: *, so a browser-side read works without a proxy.MULTICALL3_VERIFIED_CHAINS— 196 added.eth_getCodeat0xcA11bde05977b3631167028862bE2a173976CA11returned the canonical 3808-byte runtime on 2026-08-11, so vault prefetch batches its reads rather than falling back to the per-call path. Deployment presence was verified on-chain, not assumed from the deterministic deployer.
No vault is served on chain 196 yet — this is chain registration only, so no subgraph slug mapping is added.
8.21.0
Integrator highlights
Breaking: Pass
undefinedassendTransactionpositional argument tovaultDepositandvaultRedeemAction: Deposit and redeem now throw before submission if balance cannot be established or is insufficient
Action: Update calls to provider methods if you relied on implicit
'confirmed'commitment behaviorAction: Review frozen token account handling — deposit and redeem now reject frozen accounts with an error
New: Configurable Solana commitment level via
AugustSDKandSolanaAdapteroptions
Full changelog
Minor Changes
8ad6c43: fix: Solana deposit/redeem create token accounts atomically, and every balance read now agrees with the write path (AUGUST-7221)
handleSolanaDepositandhandleSolanaRedeemtreated SPL token accounts as preconditions, and where they did create one they sent it as its own transaction without awaiting confirmation. Two production failures traced to this.Deposit no longer races its own ATA creation. When the depositor had no share account, the SDK fired
createAssociatedTokenAccountInstructionviasendTransactionand then immediately simulated the deposit. Observed in production on 2026-08-11: the deposit failed withSimulation failed … Logs: []while the create was still in flight, then succeeded 17s later on retry. The empty log array means the transaction never reached program execution, so nothing was written on-chain to debug from. The on-chain program cannot self-heal here:Deposit.sender_share_accountis a plainInterfaceAccount<TokenAccount>with noinit_if_needed. Creation is now prepended to the deposit via.preInstructions(), so it is atomic with the transfer and costs one signature instead of two. This affected every first-time depositor into a vault.Redeem no longer requires the payout account to pre-exist. Redeem rejected any wallet holding no deposit-mint account with
No token account found for deposit mint. That is backwards — redeeming is precisely how a holder first receives the deposit mint — and it left shares acquired by transfer, airdrop, or market buy unredeemable through this SDK. The payout account is now created inline when absent. (A zero-balance account already satisfied the old guard, so this affected only wallets that had never held the deposit token at all.)Idempotent creation. All account creation uses
createAssociatedTokenAccountIdempotentInstruction, so a concurrent create (another tab, a wallet auto-provisioning the account) is a no-op rather than a failure. The fee-recipient account is created unconditionally on redeem, replacing agetAccountInforead followed by a separate transaction and a hard-codedsetTimeout(1000).One selection rule for every read and write. A wallet's account of record for a mint is now the one holding the largest balance, applied uniformly across
fetchUserTokenBalance,fetchUserShareBalance,fetchUserShareBalanceRawand both vault handlers. Previously each took whichever account the RPC happened to return first, an orderinggetParsedTokenAccountsByOwnerdoes not guarantee — so for a wallet holding more than one account for a mint, the balance shown and the account transacted against could be different accounts. The rule is an internal helper, not part of the public API surface.An unreadable balance — an RPC response whose
amountis not a u64 string — is now treated as unknown rather than as zero, since scoring it zero would silently demote a funded account below a dust one and reinstate the behaviour this rule exists to prevent. On the write paths this surfaces: deposit and redeem throw rather than transact against an account whose balance could not be established. The three balance readers keep their existing never-throw contract and still return their documented zero fallback, logging the failure — so read behaviour is unchanged for consumers.Deposit and redeem now check the balance, not just that an account exists. A wallet with an empty or under-funded account previously passed the guard and paid a signature to discover an on-chain insufficient-funds revert. The balance is already in hand from the account lookup, so this costs no extra RPC. Both handlers throw
AugustValidationErrorbefore submitting.Commitment is now explicit and configurable — the default is unchanged.
SolanaAdapterpreviously passed no commitment when constructing itsConnectionand nocommitmentto.rpc(), so reads and confirmations both fell through to the RPC's own'finalized'default. That default is now stated explicitly and exposed:new AugustSDK({ solana: { rpcUrl, network, commitment: "confirmed" } }); // or directly: new SolanaAdapter(endpoint, network, commitment /* default: 'finalized' */);The one setting covers reads and write-confirmations together — the vault handlers and both Anchor providers (
SolanaUtils.getProvider,getReadOnlyProvider) all derive their commitment from the sameConnectionrather than hard-coding one, so nothing can drift apart. Pass'confirmed'for a markedly faster round trip (seconds rather than tens of seconds), accepting that the state you act on can still, in principle, be rolled back.Action required if you call
getProgram(...).methods…rpc()directly. Both provider factories previously hard-codedcommitment: 'confirmed', while the connection they wrapped read at'finalized'— the inconsistency this change removes. Writes issued through that public API without a per-callcommitmenttherefore confirmed at'confirmed'before this release and now confirm at the adapter default,'finalized'. They are strictly safer but noticeably slower (tens of seconds rather than seconds). To keep the previous latency, configurecommitment: 'confirmed'— which now applies to reads and writes alike — or passcommitmentper call to.rpc(). Consumers who only usevaultDeposit/vaultRedeemare unaffected: those already confirmed at'finalized'.Configuring Solana through the legacy
providersmap leaves the commitment at the default:ISolanaConfigrequiresrpcUrlandnetwork, so a commitment-only object alongside that path is not expressible in TypeScript.Frozen accounts are no longer selected for transfers. A token issuer can freeze an account, and tokens can move neither out of nor into a frozen one. Selection now prefers a spendable account over a richer frozen one, and when every account for a mint is frozen, deposit and redeem raise
AugustValidationErrornaming the cause instead of reverting with a bare SPL0x11after the user signs. This covers all four roles: the deposit's funding account and share destination, and the redeem's share source and payout destination. The balance readers are unchanged — they still report a frozen balance, because the user does own it.Sub-unit amounts are rejected before submission. A positive UI amount below one raw unit (
1e-7into a 6-decimal mint) truncates to zero when scaled. Both handlers now re-check the scaled amount, so this raisesAugustValidationErrorinstead of clearing the balance gate (0n < 0nis false) and submitting a no-op transfer.One confirmation per transaction. Both handlers fetched a blockhash that was never used to build the transaction (
.rpc()builds and signs with its own), then ran a secondconfirmTransactionagainst that unrelated hash after Anchor had already confirmed..rpc()now owns submission and confirmation, withcommitmentpassed explicitly.sendTransactionis now ignored bySolanaAdapter.vaultDeposit,SolanaAdapter.vaultRedeem, and both underlying handlers — there is no longer a second transaction to send, and signing goes through the provider's wallet. Existing call sites keep compiling.On the two adapter methods it is a positional parameter sitting immediately before
vaultAddress. Passundefinedin that position — do not delete the argument. Deleting it shifts your vault address into thesendTransactionslot and leavesvaultAddressundefined, which falls back to the legacy single-vault PDA derivation and targets a different vault. On the underlying handlers the parameter is a named object property, so it can simply be omitted.Note that deposit and redeem may debit SOL rent from the signer for accounts they create (~0.00204 SOL each; on redeem this can include the vault's fee-recipient account). This was already true of the old two-transaction flow; it is now documented on both handlers.
8.20.1
Integrator highlights
Action: Review
getVaultRedemptionHistorycalls if using Alchemy, Infura, dRPC or QuickNode — default block range now 10k instead of 50k.Action: If using Solana or Stellar vaults, re-test
getVaultAllocationsas non-EVM identifiers are now URL-encoded instead of checksummed.New: New
determineRpcBatchMaxCountexport to derive batch size from RPC endpoint host.
Full changelog
Patch Changes
3bd6e3f: fix: honour provider RPC limits, stop crashing on non-EVM subaccounts, and cut duplicate error reporting
Five production failures, in descending event volume:
dRPC batch rejection.
createProviderhard-codedbatchMaxCount: 10, but dRPC's free tier rejects batches larger than 3 — and rejects the whole batch, so every Mezo read failed withserver response 500 … "Batch of more than 3 requests are not allowed". Batch size is now derived from the endpoint host via the newdetermineRpcBatchMaxCountexport.Non-EVM subaccounts. Every
WEBSERVER_ENDPOINTS.subaccount.*builder ran the identifier through ethers'getAddress(), so a Solana or Stellar vault operator threwTypeError: invalid addressbefore any request was made — breakinggetVaultAllocationsfor mixed-chain vaults. EVM addresses are still checksummed; other identifiers are URL-encoded.BigInt(undefined).getVaultAvailableRedemptionsread the amount field of the other subgraph schema (assetsvsshares) and threwTypeError: Cannot convert undefined to a BigInt, which emptied the returned redemption list — a claimable withdrawal silently disappeared. Absent or non-numeric amounts now coerce to0n.eth_getLogsrange.determineBlockSkipInternaldefaulted to 50 000 blocks; Alchemy, Infura, dRPC and QuickNode all cap the range at 10 000 and reject with JSON-RPC-32600, failinggetVaultRedemptionHistoryon Ethereum mainnet. The default is now 10 000 (15 batchedeth_getLogscalls per 150k-block lookback instead of 3).Duplicate reporting. A failed log-fetch chunk was captured as an issue and then re-thrown into a catch block that captured it again.
Reporting changes (no behaviour change for callers):
Per-borrower CeFi/OTC lookups that return 204/404 ("this subaccount has no such position" — the common case) are breadcrumbs instead of captured errors.
A missing portfolio fetcher for a chain type (Stellar, Sui) is a breadcrumb, and no longer forces
getVaultAllocationsto throwfailure to fetch debank response— Stellar vaults now return the CeFi/OTC/loan allocations that did resolve.AugustHistoryUnavailableErroris no longer reported: it is a designed outcome thrown to the caller, not an SDK fault.Mezo (chain 31612) errors are dropped entirely. Its public dRPC endpoint failed often enough to dominate the error stream without describing an SDK defect. This is a deliberate blind spot — genuine Mezo bugs are silenced too; remove the
MUTED_CHAIN_SLUGSentry incore/analytics/sentry.tsto restore reporting.Identical SDK errors are rate-limited to 3 per signature per minute before reaching Sentry, with the suppressed count attached to the next event that is sent (
sdk.suppressed_since_last).
8.20.0
Integrator highlights
Breaking:
getVault,getVaultLoans,getVaultSubaccountLoans,getVaultAllocationsnow throwAugustValidationErrorcodeINVALID_CHAINinstead of continuing with undefined RPC URL.Breaking:
assertKnownChainIdnow only rejects truly unknown chain IDs, not EVM chains with missingNETWORKSentries if a provider is configured.Action: Wrap calls to vault methods in try-catch to handle new
AugustValidationErrorwith codeINVALID_CHAIN.Action: If passing an unconfigured EVM chain ID, provide the RPC URL to the constructor or remove the unsupported chain from your calls.
New: New exports:
isEvmChainId,isKnownChainId,assertKnownChainId,assertEvmProviderConfigured,SUI_CHAIN_ID,NON_EVM_CHAIN_IDS.
Full changelog
Minor Changes
2c391b8: fix: vault methods now fail fast on an unroutable
chainIdinstead of continuing without an RPC URLgetVault,getVaultLoans,getVaultSubaccountLoansandgetVaultAllocationspreviously loggedMissing RPC URL for chainId Nand carried on with an undefined RPC URL. That surfaced as a cascade of misleading downstream failures —connect ECONNREFUSED 127.0.0.1:8545(ethers falling back to its localhost default),missing revert dataondecimals()reads issued against the wrong chain, andTypeError: Cannot read properties of undefined. Entirely unknown chain IDs were swallowed the same way.These methods now throw a typed
AugustValidationErrorwith codeINVALID_CHAIN:Unknown chain ID (not a supported EVM chain and not Solana
-1/ Stellar-3/ Sui101) — the call site is wrong.Supported EVM chain with no configured RPC URL — remediated by passing one to the constructor; the error message names the chain and shows the fix.
Non-EVM chain IDs are exempt from the RPC-URL check: Solana, Stellar and Sui vaults route through their adapters and never read the
providersmap.New exported helpers:
isEvmChainId,isKnownChainId,assertKnownChainId,assertEvmProviderConfigured, plus theSUI_CHAIN_IDandNON_EVM_CHAIN_IDSconstants.Callers that previously relied on these methods continuing past a missing provider will now see an error at the call site rather than an opaque RPC failure later.
Patch Changes
47f7e69: fix:
assertKnownChainIdno longer rejects an EVM chain ID missing fromNETWORKSwhen the caller configured a provider for it (e.g. chain 10 / Optimism, which ships fallback RPCs and oracle addresses but has noNETWORKSentry). Previously such a chain was rejected as "unknown" before the provider check ever ran, breaking a previously-working call.
8.19.0
Integrator highlights
New: New
attributionconstructor option withbuilderCodesand optionalchainsappends ERC-8021 calldata suffix to EVM writes.
Full changelog
Minor Changes
8ab81d0: feat: ERC-8021 attribution (Base Builder Codes) — new
attributionconstructor option ({ builderCodes, chains? }) appends the ERC-8021 calldata suffix to every EVM write: ethers vault writes via the normalized-signer wrap and cross-chain OVault viem writes viadataSuffix. Off by default; no viem version requirement.
8.18.0
Integrator highlights
Action: Check if your UI handles the new
confirmationUnknownflag to show pending instead of failed on lost confirmations.Action: Re-quote or refresh token decimals before submit if using custom decimals logic, as the SDK now caches more aggressively.
New:
isRetryableRpcErrorclassifies transient JSON-RPC transport faults vs. genuine reverts.New:
isEmptyViewResponsedetects empty responses to argument-free ERC-20 view calls.New:
retryOnTransientRpcretries with bounded exponential backoff on transient provider faults.
Full changelog
Minor Changes
32f2bc7: fix: stop reporting mined transactions as failed when the RPC hiccups mid-receipt-poll
Bumped
minorrather thanpatchper CLAUDE.md §3: although the driver is a bug fix, the change adds six exported symbols (isRetryableRpcError,isEmptyViewResponse,retryOnTransientRpc,getDecimalsOrThrow,getReceiptTokenAddressOrThrow,LP_TOKEN_ADDRESS_SELECTOR) to the public surface viacore'sexport *. No existing signature or behavior is removed or changed.safeWaitForTxpreviously only recovered from malformed-nonce RPC responses. Any other failure out oftx.wait()— most commonly a transient JSON-RPC transport fault while pollingeth_getTransactionReceipt(could not coalesce error (error={ "code": -32603 … })) — was rethrown, sovaultRequestRedeemand every other write path reported a transaction that had already been broadcast and mined as FAILED. Users then retried and hitERC20InsufficientBalance.Adds
isRetryableRpcError(error), which classifies JSON-RPC-32603/-32000, ethers' "could not coalesce error",eth_getTransactionReceiptfailures, network/timeout/fetch faults and HTTP 429/5xx as transient transport errors — while explicitly not matching genuine contract reverts (CALL_EXCEPTIONcarrying revert data,execution reverted, or a receipt withstatus === 0).missing revert datais intentionally excluded so this predicate never contradictsisExpectedRevertError.Adds
isEmptyViewResponse(error, selector?)for the onemissing revert datashape that really is a provider artefact: an empty response to an argument-free ERC-20 view call (decimals(),symbol(),name(),totalSupply()), which a deployed token cannot legitimately revert on.safeWaitForTxnow re-pollsprovider.waitForTransaction()with bounded exponential backoff (3 attempts, 250ms base) on those transport faults. It still throws on astatus === 0receipt and on a wait that times out with no receipt, and the existing nonce-parse fallback is unchanged.Failed writes now say whether the transaction reached the chain. When a write is broadcast and only its confirmation is lost, the thrown
AugustSDKError.contextcarriestxHash,broadcast: trueandconfirmationUnknown: true— enough for a UI to render a pending state instead of "failed" (and to not prompt a retry, which is how a redeem gets double-submitted). A definitive on-chain revert reportsconfirmationUnknown: false, and a write that never left carries notxHashat all. Wired throughvaultDeposit,vaultRequestRedeem,vaultRedeem,depositNative,rwaRedeemAssetand the approval path. No return type or call signature changed.Every
decimals()read in the write paths (approve, deposit, redeem, native deposit and the SwapRouter paths) now goes through a newgetDecimalsOrThrow, which shares the same cache namespace and the same in-flight dedup map as the existinggetDecimalsused by read paths. So a read-then-write flow against the same token costs onedecimals()RPC in total instead of two, and concurrent callers for an uncached token collapse to one call.getDecimalsOrThrowdiffers fromgetDecimalsonly in that it surfaces failures instead of resolvingundefined(anundefineddecimals reaching amount encoding silently means 18) and retries the transient ones.Every
lpTokenAddress()read is now retried the same bounded way. The evm-2 receipt-token lookup sits one line above thosedecimals()reads on the approve, deposit, request-redeem and SwapRouter-deposit paths, and was still a bare call — so a single truncatedeth_callresponse failed the whole write withmissing revert data (action="call", data="0xf5ae497a", …)(observed in production against the mainnet Tori Ecosystem Vault, whoselpTokenAddress()returns a real address when the provider is healthy).0xf5ae497ais added to the argument-free view selectors and exported asLP_TOKEN_ADDRESS_SELECTOR, and a newgetReceiptTokenAddressOrThrowroutes the read throughretryOnTransientRpc. Applied at every call site:vaultApprove,vaultDeposit,vaultRequestRedeem,swapRouterDeposit, the cachedgetReceiptTokenAddressreader,getVaultUserLifetimePnl,getPreviewRedemption, and the evm-2 LP branch offetchTokenPrice(which inlines the same retry becausecore/helpers/web3imports fromcore/fetcher, so sharing the helper would be a cycle). This deliberately does not hide a misrouted vault.lpTokenAddress()exists only on evm-2 vaults, so empty returndata is also the only signal that version routing put a vault in the wrong branch — and it is byte-identical to a provider blip. The retry is therefore bounded (3 attempts, ~750ms), rethrows the original error object once they are spent (identity, message,codeandtransaction.dataintact, soAugustSDKError.causeand Sentry grouping are unchanged), and has no fallback: it never substitutes another address and never resolvesnull/undefined. A transient blip is absorbed; a deterministic misroute still fails exactly as loudly as before. Unlikedecimals, the result is not cached — no vault→receipt-token mapping is memoized on the money path in this pass. Success-path RPC cost is unchanged at oneeth_callper read.providerScopenow unwraps a runner to its provider before scoping the cache key. This is a no-op for providers (ethers'AbstractProviderdefinesget provider() { return this; }), so read paths key exactly as before; it is what lets a signer-backed write share a cache entry with a provider-backed read on the same chain instead of falling back to theunknownscope.The retry loop (
retryOnTransientRpc) is exported fromcore/helpers/chain-errorso the receipt-poll fallback and the decimals reader share one implementation.
Per CLAUDE.md §7.2:
isRetryableRpcError,isEmptyViewResponse,retryOnTransientRpcandgetReceiptTokenAddressOrThroware deliberately excluded from the benchmark suite. The last is, on its success path, exactly the singlelpTokenAddress()eth_callthe evm-2 write paths already made (no cache, no extra round trip), so its latency is already covered by the existingvaultDeposit/vaultRequestRedeementries. The first two are pure synchronous classifiers over an already-caught error (stringincludesplus property reads, no RPC or I/O) that only run on a failure path already dominated by the RPC round trip that failed; the third's cost is a fixed, deliberate 250/500ms backoff, not a regression surface. The rationale is recorded alongside the other benchmark exemptions inbenchmarks/suites/sdk-methods.js. All three are covered by unit tests instead.
Patch Changes
32b60bc: fix: report the correct broadcast state when a
depositWithPermitdeposit's confirmation is lost to a transient RPC faultvaultDeposit's permit sub-path sends its single main transaction throughsafeSendTxand returns immediately on success, so the hoisteddepositTxlocal — which every other sub-path assigns and which the catch block used to read the broadcast marker — was never set. If that internal wait hit a transient transport fault, the thrown error carried notxHashin its context, so a broadcast-but-unconfirmed permit deposit was reported as never sent, reintroducing the retry-into-double-submit windowretryable-rpc-transport-errorsclosed for the other write paths. The catch now falls back to reading the marker off the error itself (errorTxBroadcastContext) whendepositTxis unset — the same mechanism already used byvaultRedeem,rwaRedeemAssetandapproveCorefor their single-tx paths.7c7c074: chore: route SDK telemetry to the
august-js-sdk-v2Sentry project
8.17.1
Integrator highlights
Action: Monitor Slack alerts for 'Missing Subgraph' per-pool notifications, now including HTTP status reasons for subgraph failures.
Full changelog
Patch Changes
f0dd06d: fix: stop billing a dead subgraph as a Sentry error on every read
The subgraph readers logged a missing subgraph URL, and a non-200 from a resolved one, at
errorlevel. Both conditions are per-vault, but the readers run on every portfolio/history request, so a handful of vaults with retired subgraphs produced over 2M Sentry error events in 30 days — the single largest consumer of the org's error quota.These paths now log at
warn(a breadcrumb, still attached to any real error that follows) and route the durable signal through the existing per-pool, TTL-deduped "Missing Subgraph" Slack alert. The non-200 branches did not alert at all before, so a URL pointing at a deleted subgraph was previously only visible as error spam; it now raises the same one-per-pool alert as a missing URL, with the HTTP status as the reason.Every reader already resolves its chain id at the top of the function for its own use, so the alert reuses that value rather than making a second
getChainIdround trip on a cold provider.Behaviour is otherwise unchanged: every reader still returns its empty result on failure. Keeping the alert is deliberate — a 404 makes these readers fall back to empty history, and silently-empty subgraph history is what made the 2026-07-09 PnL overinflation incident hard to diagnose.
8.17.0
Integrator highlights
New: IVault now exposes
withdrawalMarginSeconds(number | null) for withdrawal period display buffer.New: IVault now exposes
iatTraders(string[] | null) for IAT trader wallet addresses.New:
withdrawalMarginSecondsproperty onIVaultfor display buffer configurationNew:
iatTradersproperty onIVaultlisting IAT trader wallet addresses
Full changelog
Minor Changes
5d9f67e: Surface two backend tokenized-vault fields on
IVault:withdrawalMarginSeconds(number | null) fromwithdrawal_margin_seconds— the display buffer added on top of the on-chain lag for the withdrawal period shown to users. Null means the backend has not configured a margin and consumers should apply their own default; an explicit 0 is a real "no margin" value.iatTraders(string[] | null) fromiat_traders— IAT trader wallet addresses for the vault, in the vault chain's address format. Null when not configured.
8.16.1
Integrator highlights
Action: getVaultUserLifetimePnl now computes totalDeposited from face value instead of live oracle quotes; lifetimePnl now correctly includes vault fees.
Full changelog
Patch Changes
efffd48: fix:
getVaultUserLifetimePnlnow computestotalDepositedfrom the face value of what a user actually deposited, rescaled to the vault's own decimals, instead of re-quoting each deposit through a live price oracle. Previously,totalDeposited(and thereforelifetimePnl) drifted between calls purely from stablecoin peg noise, and approximately re-inflated deposits back toward face value — which silently excluded the vault's entry/exit fees from PnL.lifetimePnlnow correctly reflects those fees as a cost.
8.16.0
Integrator highlights
Breaking: getProgram and getProgramId now throw AugustValidationError instead of TypeError when program not deployed on network.
Breaking: Removed testnet entry from programIds mapping; canonical august_vault program is not deployed on Solana testnet.
Action: Solana adapter now targets shared august_vault program (up12…) on all networks; update integrations using retired per-vault programs.
Action: APY rates on IVaultApy are percentages (7.95 means 7.95%); do not rescale these fields.
New: IVault.freshness surface exposes apyComputedAt, shareRatioSnapshotAt, and cachedAt timestamps.
Full changelog
Minor Changes
f3dc1e6: fix(solana): target the shared august_vault program and ship the deployed IDL
Point the Solana adapter at the shared, canonical program —
up12…, now deployed under the same id on every network — instead of the retired per-vault SyrupBTC program (7B8n…) or the interim devnet deploy (C8B1…).getProgramresolves the program id from an explicitprogramIdor the per-networkprogramIdsmap, independent of the IDL passed — the IDL's embeddedaddress(a build stamp) is only a last-resort fallback when nonetworkis known. This closes a sharp edge where a non-reference-equal copy of the built-in IDL on a non-mainnet network could resolve to the embedded mainnet program id.Refresh the shipped IDL to the deployed versioned multi-vault interface (fetched from the devnet on-chain IDL), replacing the stale pre-versioned copy. Read paths (
VaultStatedecode) and thedeposit/redeeminstructions are unchanged; the refresh addsclose_vault/set_aum_limits/update_share_token_metadataand the versionedinitialize. A CI drift guard (solana-idl-drift) fails if the committed IDL diverges from the deployed devnet program.
2da4cad: fix(solana): honour custom IDL program addresses, drop the undeployed testnet mapping
SolanaAdapter.getProgramnow accepts an optionalprogramIdoverride and no longer discards theaddresson a caller-supplied IDL. Resolution order is explicitprogramId→ custom IDLaddress→ per-network default → the IDL's embedded build stamp. A copy of the SDK's bundledvaultIdlstill defers to the network default, so the devnet-silently-targets-mainnet edge stays closed.Removed the
testnetentry fromprogramIds: the canonicalaugust_vaultprogram is not deployed on Solana testnet, so the mapping handed callers an address with no executable behind it.getProgramandSolanaAdapter.getProgramIdnow throwAugustValidationErrornaming the deployed networks instead of returning a dead address (getProgramIdpreviously threw a bareTypeError).The Solana IDL drift guard now validates the program the SDK actually targets (
up12…) by pinning its deployed binary across devnet/mainnet and decoding liveVaultStateaccounts against the committed layout, rather than only comparing the structurally-matchingC8B1…reference IDL.
8c306f7: feat: surface per-vault data-provenance timestamps as
IVault.freshnessMaps the backend's new
freshnessobject ontoIVaultfor every tokenized-vault read on both the August and Upshift surfaces:apyComputedAt(whenhistorical_apy/ TVL / drawdown were last recomputed),shareRatioSnapshotAt(newest persisted share-price snapshot), andcachedAt(when the backend assembled the response body). AshareRatioSnapshotAtlater thanapyComputedAtmeans a snapshot has landed that the APY has not been recomputed from yet — the staleness signal a UI needs to render "data as of X" instead of implying share price and APY are equally current (AUGUST-6124).All three are independently nullable and are never defaulted from one another.
shareRatioSnapshotAtis populated regardless ofload_snapshots, so it is present on the basic and sub-accounts views too. Values are passed through verbatim as RFC 3339 UTC strings with the trailingZ. Additive and non-breaking:freshnessis null when the backend does not report it, and the existing top-levelcachedAtis unchanged.freshnessis read off the same response body ashistorical_apy, so the timestamps always describe the payload they annotate — including when that body is served from the SDK's in-process response cache.No new RPC or network calls — the field rides along on responses the SDK already fetches, and the mapping is a synchronous three-key rename.
Patch Changes
75d5168: docs: document the unit contract on
IVaultApyEvery rate on
IVaultApy(apy,liquidApy,pointsApy,campaignApy,underlyingApy) is a percentage —7.95means 7.95%. The backend reports decimal fractions and the SDK multiplies by 100 exactly once, uniformly, across all of them. That convention was never written down, which let a consumer scale a subset of the fields twice and display 1/100th of their real contribution (AUGUST-6967).Documentation only — no behaviour or value changes.
rewardsClaimable/rewardsCompoundedare also now marked as token amounts rather than rates.
8.15.0
Integrator highlights
Action: Check
is_show_compound_apyflag to decide whether display simple or compound APY to usersAction:
getVaultUserLifetimePnlnow throwsAugustHistoryUnavailableErrorwhen deposit/withdrawal history unavailableNew:
historical_compound_apyfield on/tokenized_vaultwithapy_override.is_show_compound_apyflagNew:
AugustHistoryUnavailableErrorandassertPnlHistoryConsistentexported for history validation
Full changelog
Minor Changes
2277991: feat: expose compound-annualized historical APY (AUGUST-6765)
/tokenized_vaultnow returnshistorical_compound_apy(same 1/7/30-day horizon shape ashistorical_apy) plusapy_override.is_show_compound_apyselecting which annualization convention the UI should display. The SDK now types both fields and passeshistorical_compound_apythroughbuildBackendVault/buildFormattedVaultontoIVault, so consumers can honor the flag. Both fields are optional; absence means simple (existing behavior).ab1df85: feat: guard lifetime PnL against unavailable transaction history
getVaultUserLifetimePnlnow throws a typedAugustHistoryUnavailableError(codeHISTORY_UNAVAILABLE) when a wallet holds a live on-chain position but the deposit/withdrawal history failed to load (empty deposits and empty withdrawals). Previously this state degenerated to reporting the entire position as profit — the 2026-07-09 over-inflation incident. Adds the exportedassertPnlHistoryConsistentguard and theAugustHistoryUnavailableErrorerror class.
8.14.0
Integrator highlights
Breaking: IVault.fees.isManagementWaived and isPerformanceWaived now return fully-resolved booleans instead of raw backend flags.
Action: Review code reading isManagementWaived or isPerformanceWaived to confirm resolved boolean semantics match your use case.
New: resolveFeeWaived helper function to evaluate fee-waiver state against clock and TVL latch.
New: decodeRevertData, extractRevertFromErrorText, lookupSelector, simulateCall, and readTokenState helpers for transaction failure diagnostics.
New: Non-EVM fee-waiver path now correctly resolves state instead of hardcoding false.
Full changelog
Minor Changes
fae58f3: feat: resolve fee-waiver state in the SDK (AUGUST-5584).
IVault.fees.isManagementWaivedandisPerformanceWaivednow carry the fully-resolved "show Fee Waived right now?" boolean instead of the raw backendplatform_fee_override.is_fee_waivedflag. Adds the pure helperresolveFeeWaived(isFeeWaivedToggle, waivedUntilDate, waivedUntilTvl, now?): the backend toggle is the master enable and one-way TVL latch (SDK does no TVL math, never readslatest_reported_tvl), while the SDK evaluates the date window live against the clock. Also fixes the non-EVM (Solana/Stellar/Sui) mapping path, which previously hardcoded both booleans tofalse. The*_waived_until_date/*_waived_until_tvlraw fields remain exposed for tooltip rendering. Behavioral change for consumers reading the two booleans — they were unresolved before.70c960b: feat: add revert-decode helpers —
decodeRevertData(offline decode ofError(string),Panic(uint256), and custom errors against an OZ ERC-6093 / SafeERC20 / LayerZero / vault-ABI corpus, extendable viaextraAbis),extractRevertFromErrorText(recovers revert data, action, code, and transaction fields from an ethers v6 error string, tolerant of truncation),lookupSelector(openchain.xyz / 4byte.directory signature lookup for unknown selectors),simulateCall(eth_callreplay that returns fresh, auto-decoded revert data), andreadTokenState(bounded symbol/decimals/balance/allowance probe set plus issuer compliance gettersisAccountFrozen/isBlacklisted/isFrozen). Together these let alert-triage tooling decode why a transaction failed atestimateGas, where no transaction hash ever exists.
8.13.0
Integrator highlights
Action:
getVaultVersion(V1) is deprecated; migrate togetVaultVersionV2for correct multi-asset classificationAction: Static
SWAP_ROUTER_ELIGIBLE_VAULTSandisSwapRouterEligibleare deprecated in favor of on-chain resolversNew:
getSwapRouterEligibleVaults(chainId)resolves eligible vaults on-chain with 5-min cacheNew:
getSwapRouterWhitelistedTokens(chainId)resolves chain token allowlist by scanning eventsNew:
SWAP_ROUTER_NAMESandgetSwapRouterName(chainId)provide router display names
Full changelog
Minor Changes
802b24f: feat: add
getSwapRouterEligibleVaults(chainId)— resolves the SwapRouter's eligible-vault set on-chain (VaultEnabledevent scan +vaultInfo.referenceAssetverification, fail-closed, 5-min cache) on the SDK root andAugustVaults; addSWAP_ROUTER_NAMES/getSwapRouterName(chainId)for the periphery contract's display name ('Upshift Swap Router' on mainnet). Deprecates the staticSWAP_ROUTER_ELIGIBLE_VAULTSset andisSwapRouterEligible(kept functional as zero-RPC fallbacks) in favor of the on-chain resolver.b52a1ab: feat: add
getSwapRouterWhitelistedTokens(chainId)— resolves a chain's SwapRouter token allowlist by scanningTokenEnabledevents and verifying each against the on-chainwhitelistedTokensmapping (the mapping is not enumerable). Exposed on the SDK root and the vaults module; lets UIs render swap-and-deposit token options without a hardcoded candidate list.
Patch Changes
823b5d9: deprecate:
getVaultVersion(V1) is now marked@deprecatedin favour ofgetVaultVersionV2. V1 classifies multi-asset vaults only against the staticMULTI_ASSET_VAULTSlist, so any vault missing from it is misclassified asevm-1(the root cause of the 2026-07-06 Sentora preview/simulation break).getVaultVersionV2reads the backendinternal_typeand falls back to the static list only as a safety net. V1 is retained as a non-breaking shim and scheduled for removal in the next major.
8.12.0
Integrator highlights
New:
getSwapRouterDepositResultresolves post-execution deposit amount and shares from mined SwapRouter events.New:
IVaultUserHistoryItemnow exposesassetInandsharesfields.New:
SWAP_ROUTER_DEX_AGGREGATORincludes anamefield for human-readable aggregator display.
Full changelog
Minor Changes
b3ea699: feat: add
getSwapRouterDepositResult(andEVMAdapter.getSwapRouterDepositResult) to resolve the real, post-execution amount and shares from a mined SwapRouter deposit's ownDepositevent, instead of relying on the pre-trade quote. Also adds anamefield toSWAP_ROUTER_DEX_AGGREGATORfor displaying the aggregator's human-readable name instead of its address.a093373: feat: expose
assetInandsharesonIVaultUserHistoryItem—assetInlets consumers render the actual deposited token for multi-asset (pre-deposit) vaults instead of guessing the vault's first deposit asset;sharessurfaces the receipt-token amount burned on a withdraw request, whose settled asset value isn't known until processing
Patch Changes
6d9738a: refactor: move
getSwapRouterDepositResultfrommodules/vaults/gettersdown tocore/helpers/swap-routerto break theadapters/evm↔modules/vaults/getterscircular dependency (the repo's zero-cycle CI gate). The symbol is re-exported from its original location, so every existing import path and the public API are unchanged; no behavior change.add shares
011740e: perf: batch the per-vault
balanceOf/lagDurationreads behindgetVaults({ wallet })andgetVaultPositionsinto chunked Multicall3aggregate3calls, grouped by chain (10 calls per chunk). Enabled only on chains where the canonical Multicall3 deployment was verified on-chain viaeth_getCode(allNETWORKSchains except Citrea 4114, which keeps the per-call path, as do non-EVM vaults) — 15 chains verified 2026-07-14, Tempo verified in a follow-up pass on 2026-07-15. Each batched call usesallowFailure, so a single reverting vault (e.g. paused) falls back to its own per-vault reads instead of affecting the rest of the batch — failure behavior is unchanged from the per-call path. No public API change. Measured withbenchmarks/request-counter.js(cold cache, wallet with 62 vaults across Ethereum + Avalanche): 83 → 54 RPC HTTP requests (~35% fewer; 124 per-vaulteth_calls collapse into ~13 aggregated calls). The prefetch's cold-cache receipt-token (lpTokenAddress) resolution for evm-2 vaults is capped at 10 concurrent reads per chain, so a wallet with many uncached evm-2 vaults can't burst an unbounded number of simultaneous reads before the batch fires.
8.11.0
Integrator highlights
Action: Pass optional
sorobanRpcUrltoAugustSDKorStellarAdapterto inject a keyed Soroban RPC endpoint.New:
IVaultUserHistoryItemnow exposesassetInfield for multi-asset vault deposits.New: Stellar adapter supports health-gated RPC failover with optional
sorobanRpcUrloverride on SDK/adapter/per-call.New: Failover retries idempotent Soroban operations on node-specific simulation errors.
Full changelog
Minor Changes
a093373: feat: expose
assetInonIVaultUserHistoryItemso consumers can render the actual deposited token for multi-asset (pre-deposit) vaults instead of guessing the vault's first deposit asset84f6a59: feat(stellar): health-gated Soroban RPC failover + optional consumer RPC override (AUGUST-6653)
The Stellar adapter resolved a single Soroban RPC endpoint and ran every read, transaction build, and submit against it. When that provider node stalled — as
soroban-rpc.mainnet.stellar.gateway.fmdid at the Protocol 27 upgrade boundary, freezing behind the network head so every simulation failed withsetting ContractComputeV0 is not present in the snapshot— there was no way to route around it, and deposits/reads failed withAugustSDKError: Soroban simulation failed: …. (The EVM path already hadFALLBACK_RPC_URLS; Stellar had none.)Health-gated failover.
queryContract,buildSorobanTx, andsubmitStellarTransactionnow obtain their server from an internalgetHealthyServer, which probes the configured endpoints in priority order viagetHealth(), uses the first healthy one, and falls back to the first reachable endpoint (so the caller still surfaces the node's real error) when none report healthy. A malformed configured endpoint (e.g. a typo'd override) is skipped rather than aborting the probe, so a bad primary can't disable every fallback. Mainnet gainshttps://mainnet.sorobanrpc.comas a keyless public fallback. The healthy-endpoint choice is cached ~30s, and concurrent callers on a cold cache share a single in-flight probe (no stampede on the parallel-read hot path).Operation-level failover. Health-gating only proves an endpoint answered
getHealth()— a node can still hang or return a method-specific error on the real call, and the choice is cached ~30s. SoqueryContractandbuildSorobanTxnow run their (idempotent) RPC work through a failover wrapper that retries the operation against the remaining endpoints on a retryable failure, time-boxed so a hung node can't stall the call. Crucially, retryable failures include node/snapshot simulation errors (e.g. the… is not present in the snapshotpost-upgrade case): these arrive as a simulation error but are node-specific, so they fail over — only a genuine contract revert (and other deterministic outcomes: unfunded account, archived-state restore) is terminal and never retried across nodes. The wrapper skips the endpoint the health-gated attempt already used (no double timeout; a sole endpoint isn't retried for nothing) and promotes a working fallback into the cache so the next call starts there. During a sustained outage the endpoint set is negative-cached (short TTL) even on the read/build path, so subsequent reads fast-fail on the primary rather than re-probing and re-looping every endpoint per call — the load amplification the negative cache exists to prevent. Submission is deliberately excluded — re-sending a signed transaction across endpoints risks a double-submit, so it needs sequence/DUPLICATE-based idempotency rather than blind retry.Optional consumer RPC override (new, additive API). Mirroring the existing
solanaconfig,new AugustSDK({ stellar: { rpcUrl, network } })now injects a Soroban RPC endpoint (e.g. a keyed Alchemy URL) — the SDK does not embed any key. The override becomes the primary with the built-in public endpoints kept behind it as failover. Also exposed via theStellarAdapterconstructor (new StellarAdapter(network, { sorobanRpcUrl })), an optional per-callsorobanRpcUrlon the deposit/redeem params and the getter/submit functions (a per-call value wins over the adapter-level one), and threaded into thevaultsmodule sogetVaults/getVaultPositionsStellar reads honor the override too. All additions are optional — existing callers are unaffected.Log & telemetry safety. Health-check warnings redact the RPC URL to protocol+host; the analytics sanitizer treats
sorobanRpcUrl/rpcUrlas sensitive and scrubs provider path-embedded keys (e.g. Alchemy/v2/<key>) from free-form strings and object values (not just named fields); and the failover path scrubs every configured URL from the message and chainedcauseof the error it throws. So a keyed provider endpoint — whether a per-call override captured as an instrumented argument or embedded in an SDK error string — never leaks its API key into SDK logs, telemetry, crash reporters, or a surfaced error.RPC cost: adds one lightweight
getHealthprobe before Soroban operations, cached ~30s per endpoint set (keyed by the full ordered list) and de-duped across concurrent callers — not per call.
8.10.0
Integrator highlights
Action: Check for
ACCOUNT_NOT_FUNDEDerror code in write operations to prompt user top-up instead of generic error handling.New: Write helpers (
vaultApprove,vaultDeposit,vaultRequestRedeem,vaultRedeem,depositNative,rwaRedeemAsset) now throw typedAugustValidationErrorwith codeACCOUNT_NOT_FUNDEDfor insufficient gas/L1-fee failures.New: Export
isInsufficientFundsError(error)classifier to detect insufficient-funds conditions.
Full changelog
Minor Changes
b774e66: feat: classify insufficient-gas/L1-fee failures on vault write paths
When a chain node rejects a write because the sender can't cover gas — or, on rollups such as Citrea, the extra L1 data-availability fee — ethers v6 surfaces an opaque
CALL_EXCEPTION/ "missing revert data" that was previously wrapped as a genericUNKNOWNerror and logged as an SDK fault. The real reason lives only in the nested provider error (error.info.error.message).The write helpers (
vaultApprove,vaultDeposit,vaultRequestRedeem,vaultRedeem,depositNative,rwaRedeemAsset) now detect this case and throw a typedAugustValidationErrorwith codeACCOUNT_NOT_FUNDED, so a consuming UI can branch onerr.codeto prompt the user to top up instead of string-matching. These failures are also demoted in telemetry (breadcrumb, not a billed Sentry issue) since they are a wallet-funding prompt, not a defect.Adds an exported
isInsufficientFundsError(error)classifier for callers that want to detect the same condition directly.
8.9.0
Integrator highlights
New:
AugustApiaddsgetTimelockRequests,getVaultPerformanceFees,getVaultOracleClassificationfor governance and metrics.New:
AugustApiaddsgetOtcPositions,getOtcMarginRequirements,getCuratorVaultSubaccounts,getCuratorVaultWhitelistfor OTC and curator operations.New:
AugustApiaddsgetDashboardLoans,getDiscountFactors,getCollateralExcessOrDeficit,simulateCollateralfor loan-book and risk.New:
AugustSubAccountsaddsgetSubaccountTransactions,getSubaccountLoanByAddress,getSubaccountDebank, andAugustApi.getRevertReason.New:
AugustSubAccounts.getAllSubaccountsreturns paginated directory of all August subaccounts (admin-only).
Full changelog
Minor Changes
29936be: feat: add governance & metrics read methods to
AugustApi(sdk.apiModule) —getTimelockRequests(timelock/governance requests for a vault+chain),getVaultPerformanceFees(backend-computed performance fees over a period), andgetVaultOracleClassification(public NAV-oracle classification table), withITimelockRequest,IVaultPerformanceFees,IOracleClassification, andIOracleClassificationRowresponse types.29936be: feat: add OTC & curator read methods to
AugustApi(sdk.apiModule) —getOtcPositions(all tracked OTC positions),getOtcMarginRequirements(margin requirements, optionally filtered by counterparty/payer),getCuratorVaultSubaccounts(subaccounts linked to a vault), andgetCuratorVaultWhitelist(EVM-only on-chain whitelist status), withIOtcPositionRead,IOtcMarginRequirement, andICuratorWhitelistStatusresponse types (getCuratorVaultSubaccountsreusesIWSSubaccountListItem).29936be: feat: add loan-book & risk read methods to
AugustApi(sdk.apiModule) —getDashboardLoans(admin-only global loan book),getDiscountFactors(token collateral-haircut ladders),getCollateralExcessOrDeficit(per-subaccount collateral excess/deficit), andsimulateCollateral(read-only collateral simulation), withILoanBookInfo,IDiscountFactorLadder,ICollateralExcessOrDeficit,ICollateralSimulationInput, andICollateralSimulationResultsresponse types.AugustApinow extendsAugustBaseso it can reach the configured August API key.29936be: feat: add tx-triage & activity read methods —
AugustSubAccounts.getSubaccountTransactions(authenticated/transactions/v2),AugustSubAccounts.getSubaccountLoanByAddress(admin-only single-loan detail),AugustSubAccounts.getSubaccountDebank(cross-chain DeBank positions), andAugustApi.getRevertReason(public transaction revert-reason decode), withISubaccountTransaction,ILoanBookInfo(reused),ISubaccountDebank/IDebankAccountData, andIRevertReasonresponse types.acf2a4d: feat: add
AugustSubAccounts.getAllSubaccounts— paginated directory of all August subaccounts (admin-onlyGET /subaccountbackend endpoint), withIWSSubaccountListItem/IWSSubaccountListChainresponse types
Patch Changes
7c86f9f: fix: register the Monarq XRP Yield Vault (Flare) in
VAULT_ALLOCATION_SUBACCOUNTSso its Lending Allocation Breakdown and borrower subaccount surface (AUGUST-6485). Covered by a regression test that pins the entry.
8.8.0
Integrator highlights
Action: Deposit history now resolves decimals from each deposit's
assetIntoken instead of vault decimals; re-fetch and re-render deposit amounts if previously cached.Action: Native deposits now normalize against 18 decimals via
EVM_NATIVE_DECIMALSconstant; verify rendered native deposit amounts match expected values.New: Optional
publicApiBaseUrlin SDK constructor config to override the public vault-catalog API base URL.New: New
setPublicApiBaseUrlandgetPublicApiBaseUrlfetcher overrides following thetimeoutMspattern.
Full changelog
Minor Changes
98176f4: feat: allow overriding the
publicvault-catalog API base URLAdds an optional
publicApiBaseUrlto the SDK constructor config (backed by a newsetPublicApiBaseUrl/getPublicApiBaseUrlfetcher override, mirroring the existingtimeoutMs/setSdkRequestTimeoutpattern). It repoints the unauthenticatedpublicserver base — the onegetVault/getVaults/fetchTokenizedVaultread from viafetchAugustPublic— so a non-prod deployment can serve its vault catalog from an isolated backend (e.g. a staging API serving staging-only vaults).Defaults to the compiled-in prod base (
https://api.augustdigital.io/api/v1) when omitted, so production behaviour is unchanged. Invalid or non-http(s) URLs are ignored (warned) so a bad env value can't break fetches.
Patch Changes
13f0dc9: fix: normalize deposit history against the deposited asset's own decimals
Multi-asset (pre-deposit / evm-2) vaults accept deposit tokens whose decimals differ from the vault share token. User- and vault-history reads tagged every deposit with the vault's decimals, so an 18-decimal RLUSD deposit into the 6-decimal Sentora USD vault rendered ~1e12× too large ("500B TOKEN"). Deposit rows now resolve decimals from their
assetIntoken; single-asset vaults are unchanged.a5e4370: fix: normalize native-token subgraph deposits against 18 decimals instead of 0/vault decimals
Native deposits carry a sentinel
assetIn(the zero address or the EIP-7528NATIVE_ADDRESS) that has no on-chaindecimals().getDecimals(ZeroAddress)returned0(which the?? decimalsfallback can't override) andgetDecimals(NATIVE_ADDRESS)reverted to the vault's decimals — either could misrender a native deposit's amount by up to ~1e18×.buildDepositAssetDecimalsnow maps both sentinels to the newEVM_NATIVE_DECIMALS(18) constant.
8.7.1
Integrator highlights
Action: Provide subgraph URLs via backend vault metadata instead of relying on SDK URL fabrication.
Action: Non-EVM vaults (Solana/Stellar) now correctly skip EVM subgraph routing and no longer fail on history fetch.
Full changelog
Patch Changes
62c42c2: fix: stop fabricating dead subgraph URLs and stop routing non-EVM vaults through the EVM history path
Two fixes surfaced while debugging missing Citrea vault data:
getDefaultSubgraphUrlno longer fabricates a Goldsky URL from the chain name and vault symbol. That guess was unreliable — the chain name isn't the subgraph slug (ethers reports Citrea asunknown), a vault's symbol isn't its subgraph name (EctUSDvsearn-ctusd), and the path used a legacy hosted-service segment. The bogus URL 404'd silently, so a missing subgraph read as "no data". It now returnsundefined, so callers hit their existing "Missing Subgraph" branch (warn + alert). Subgraph URLs must come from backend vault metadata. That alert branch was previously unreachable (the fabricated URL was always truthy); it is now deduped per pool so a metadata-less vault surfaces once rather than flooding the webhook on every read.getUserHistoryandgetSubgraphUserHistoryno longer route non-EVM (Solana / Stellar) vaults into the EVM subgraph path. The Solana RPC is registered under chainId -1, so Solana vaults previously passed the provider filter and triggeredeth_chainIdagainst the Solana RPC, failing with "eth_chainId is not available on SOLANA_MAINNET" on every history fetch. Both the dispatch filter and the function now gate on an EVM address.
e8b862a: fix: detect subgraph schema at runtime so History and Pending Withdrawals populate for every vault
Subgraph reads chose their field schema (old snake_case vs new camelCase) from whether the vault symbol appeared in the deprecated
SUBGRAPH_VAULT_URLSmap. A newly-added vault whose subgraph was deployed from the old template (e.g.august-citrea-earn-ctusd) is absent from that map, so the SDK queried new-schema field names (blockNumber/blockTimestamp/transactionHash) the subgraph does not expose. The subgraph returned GraphQL errors with nodata, and the reads collapsed to empty — silently emptying the Portfolio's Pending Withdrawals and History tabs while the vault, provider and RPC were all healthy.The schema is now probed once per subgraph URL (
resolveSubgraphSchema, cached) and drives the field selection in every subgraph read — withdrawal requests, processed withdrawals, combined withdrawals, user history, and vault history. Across a page's reads this adds at most one lightweight query per subgraph; the result is transparent to callers, which continue to see the internal (snake_case) shape.
8.7.0
Integrator highlights
Breaking: vaultDeposit no longer routes through SwapRouter; use swapRouterDeposit for swap-based deposits.
Breaking: VAULTS_USING_SWAP_ROUTER renamed to SWAP_ROUTER_ELIGIBLE_VAULTS; vaultUsesSwapRouter renamed to isSwapRouterEligible.
Action: Migrate from deprecated VAULTS_USING_SWAP_ROUTER and vaultUsesSwapRouter to new names before next major version.
Action: Re-quote and call swapRouterDeposit if you were relying on implicit SwapRouter routing via vaultDeposit.
New: New swapRouterDeposit method for explicit SwapRouter deposit routing with asset path selection.
Full changelog
Minor Changes
1d92be0: feat(swap-router): add explicit
swapRouterDepositdeposit methodNew high-level method
augustSdk.evm.swapRouterDeposit(options)(and the standaloneswapRouterDeposit(signer, options)export) that always routes a deposit through the on-chainSwapRouter, reading the vault's reference asset and decimals on-chain and picking the correct path fromdepositAsset(direct deposit, native wrap, or a swap to the reference asset with a fail-closed aggregator quote).This gives the client an explicit opt-in to SwapRouter deposits instead of depending on
vaultDeposit's implicitVAULTS_USING_SWAP_ROUTERallowlist routing — the mechanism that accidentally swapped a native-deposit multi-asset vault (Sentora USD).vaultDepositis unchanged; use it for native/adapter deposits andswapRouterDepositfor SwapRouter deposits.282dc2b: feat: expand the MCP server into a fuller read/analytics suite (19 new tools)
SDK — new
getVaultActivity({ vault, chainId, sinceTs, untilTs, types }): the vault-wide counterpart togetVaultUserHistory, returning every deposit/withdrawal event for a pool (not scoped to one wallet). Its subgraph reader now paginates past the 1000-row page cap and stops early once it pages past thesinceTswindow, so busy vaults are no longer silently truncated.MCP — 19 new tools:
Activity/flow:
vault_activity(per-vault flow feed + computed summary: deposit/withdrawal counts, volumes, net flow, unique actors),activity_ranking("which vaults had the most deposits last week"),user_activity,user_transfers.Reads:
total_deposited,token_price,vault_withdrawals,vault_pnl,vault_annualized_apy,withdrawal_requests_status.Subaccounts:
subaccount_summary,subaccount_health_factor,subaccount_loans,subaccount_cefi_positions,subaccount_otc_positions.Ops:
ops_health,ops_redemptions(parity with theaugust opsCLI).LayerZero:
layerzero_deposits,layerzero_redeems.
config — new Zod result schemas backing all of the above.
ef0bdf6: feat(swap-router): fully separate SwapRouter routing from
vaultDepositvaultDepositno longer auto-routes any vault through the SwapRouter — it is now purely the native / multi-asset / adapter path. This removes the implicit, registry-driven routing that could silently swap a natively-accepted asset (e.g. depositing RLUSD/PYUSD/USDT into the multi-asset Sentora USD vault, or forcing a non-underlying token through a swap). Any-token swap deposits are the explicit, opt-in job ofswapRouterDeposit.The registry is now eligibility metadata, not a routing switch:
VAULTS_USING_SWAP_ROUTER→ renamedSWAP_ROUTER_ELIGIBLE_VAULTSvaultUsesSwapRouter→ renamedisSwapRouterEligible
Both old names remain as
@deprecatedaliases for one release. The set now marks vaults whose UI may offer the (opt-in) swap-router deposit surface — consumed by app UIs and, optionally, byswapRouterDepositas a fail-fast check — and is never read byvaultDeposit. Sentora USD is the initial eligible vault; its native assets still deposit viavaultDeposit, only foreign tokens route throughswapRouterDeposit.
Patch Changes
3f74779: fix(solana): surface the real Anchor revert reason in deposit/redeem errors
handleSolanaDeposit/handleSolanaRedeembuilt their wrapped error frome instanceof Error ? e.message : 'Unknown error'. When an Anchor program reverts with a recognized error code,@coral-xyz/anchor'stranslateErrorreturns aProgramErrorwhose constructor callssuper()with no argument — so.messageis the empty string by construction (the real reason lives on.msg/.code, andAnchorErrorputs it on.error.errorMessage/.error.errorCode.number). Every recognized on-chain revert therefore surfaced — and paged Slack — as"Solana deposit failed: "with nothing after the colon, discarding the numeric code needed to tellVaultPaused(6008) fromInsufficientAmount(6002) from an account-constraint violation.Both catch blocks now route the caught error through a new
describeSolanaErrorhelper that prefersAnchorError.error.errorMessage/errorCode.number, thenProgramError.msg/code, then a non-empty.message, then.toString(), and only falls back to an actionable"please try again"for a genuinely reason-less throwable (rather than an "unknown error" admission to the user; the raw throwable is still preserved oncauseand in telemetry). The message becomes e.g.Solana deposit failed: Vault is paused (code 6008).causeand structuredcontexton the thrownAugustSDKErrorare unchanged; no public API changes.
8.6.1
Integrator highlights — internal changes only; no integrator action needed.
Full changelog
Patch Changes
543442d: fix: show pending withdrawals for new-schema vaults (e.g. Clearstar Prism)
getWithdrawalRequestsWithStatusprunes requests outside a block-based lookback window viaNumber(req.block_number) >= blockCutoff. New-schema subgraphs expose the block height asblockNumber, butNEW_WITHDRAWALS_REQUESTED_QUERY_PROPSreturned it un-aliased, soreq.block_numberwasundefined,Number(undefined)wasNaN, andNaN >= blockCutoffdropped every request. The endpoint returned[], silently emptying the Pending Withdrawals tab for every vault on the new subgraph schema (any metadata-sourced vault not in the legacySUBGRAPH_VAULT_URLSlist) — while transaction history, which is sourced independently, still listed the redeem.The new-schema withdrawal query props now alias
block_number: blockNumber, matching the existing aliasing used fortransactionHash_/timestamp_(and already applied in the transfer props). The aliases on the processed/withdrawals prop sets are not read today but are added for consistency with the sharedISubgraphBasecontract to prevent the sameNaNprune recurring. No public API or thrown-error behaviour changes.a5dd13b: fix: reduce Sentry transaction volume and fix data quality issues in analytics instrumentation
Reduce default
tracesSampleRatefrom1.0to0.1— captures a statistically valid 10% sample while cutting transaction event volume by ~90%Remove
captureConsoleIntegration— SDK errors already route throughLogger.setSentrySink; the integration was redundantly capturing consumer appconsole.errorcalls as SDK error eventsAdd
beforeSendTransactionsub-sampling for thenetworkcategory (switchNetwork, updateWallet, clearWallet, setSigner) — these fire on every wallet/chain update and are high-frequency relative to their dashboard signal value; effective rate drops to ~1% of callsRemove redundant
setTagcalls forsdk.category,sdk.chain, andsdk.last_chainIdfromtrackMethodCall— these values are already recorded as span attributes; the global mutations were contaminating subsequent unrelated events with stale tag valuesRemove
setMeasurementcalls from the sync method tracking path — sync methods have no span of their own, so measurements were attaching to a random parent transaction and overwriting its counters
14c56ca: fix: stop billing user-rejected transactions and expected on-chain reverts as Sentry issues
Wallet user-rejections (deposit/redeem/approve) and routine read reverts (probing a function a vault doesn't implement) were logged at
errorlevel, turning normal product behaviour into high-volume billed Sentry issues. They are now classified via a newisUserRejectionError/isExpectedRevertErrorhelper and demoted towarn(Sentry breadcrumbs, not issues); genuine failures are unchanged and still surface as errors. A narrowignoreErrorsbackstop also drops user-rejection and localhost-node (:8545) noise at the transport. No public API or thrown-error behaviour changes.
8.6.0
Integrator highlights
Action: Update code using
getVaultTvl— it now returns assets under management, not share count.Action: Check
fetchTokenPricesFromCoinGeckofor typed errors:AugustValidationErrorfor unmapped symbols,AugustRateLimitErrorfor 429 responses.Action: Verify archived-vault user history calculations; deposit asset decimals now propagate through PnL correctly.
Full changelog
Minor Changes
15c99c1: feat: serve user history for archived vaults from the backend Mongo snapshot
getVaultUserHistory/getSubgraphUserHistorynow route archived vaults to the backend/upshift/vault_historyREST endpoint instead of their Goldsky subgraph, so deposit/withdraw history survives retiring those subgraphs. The archived set is fetched from the backend (fetchArchivedVaults, cached) — the routing source of truth — so a vault is only rerouted once its history has been backfilled. AddsfetchArchivedVaultsand asyncisArchivedVault, plus thetokenizedVault.userHistory/tokenizedVault.archivedVaultsendpoints. Return shape (ISubgraphUserHistoryItem, types deposit / withdraw-processed / withdraw-request) is unchanged.cd53624: feat(stellar): classify unfunded Stellar accounts under a dedicated
ACCOUNT_NOT_FUNDEDerror code (AUGUST-6468)When a Soroban deposit/redeem targets a source account that has never been activated,
buildSorobanTxnow throws anAugustValidationErrorwith the newACCOUNT_NOT_FUNDEDcode instead of the genericINVALID_INPUT. This is an expected, user-actionable condition (the address just needs ≥1 XLM), so giving it its own code lets it group on its own key in telemetry rather than spamming the generic-error alert bucket. The remediation message and structured context (sourceAddress,method,contractId, original error ascause) are unchanged.ACCOUNT_NOT_FUNDEDis added to the exportedAugustErrorCodeunion and to the codes accepted byAugustValidationError— additive, so existing consumers narrowing onAugustErrorCodeare unaffected.5f47a00: fix(swap-router): pin ParaSwap to a single contract method and fail closed on router/selector drift
vaultDepositthrough the SwapRouter now constrains ParaSwap to one generic contract method (swapExactAmountIn) via the/pricesincludeContractMethodsfilter, so the resulting calldata's selector is deterministic. After fetching the quote it asserts the quote'srouterand payload selector match the newSWAP_ROUTER_DEX_AGGREGATORentry for the chain, throwing a clearAugustValidationErrorinstead of letting the deposit revert on-chain withInvalidRouter()/InvalidNotWhitelisted().Adds the exported
SWAP_ROUTER_DEX_AGGREGATORconstant (the single source of truth tying the off-chain swap-leg builder to the on-chain router whitelist) and an optionalcontractMethodfield onfetchSwapQuote's request.93a983c: feat: surface per-reward backend logos via
additionalPointsDetailedgetVaultRewardsnow emitsadditionalPointsDetailedonIVaultRewards, pairing each reward's display label with its backend-providedimg_url. Consumers can resolve a reward's logo from thisimgUrlfirst and fall back to a bundled asset only when absent — so a newly-added reward with a backend logo (e.g. "Cores") renders its icon without any client-side keyword mapping. Adds theIVaultRewardDetailtype, which carries the reward's stableidas the join key (labels are display-only and not guaranteed unique).
Patch Changes
34dc7c6: chore: bump TypeScript
target/libto es2022 so modern APIs (e.g.Object.hasOwn) type-check. Emitted output now targets es2022 — requires Node 16.9+ / modern browsers.1b106e7: fix(coingecko): surface typed errors for unmapped symbols and non-2xx responses
fetchTokenPricesFromCoinGeckopreviously silently returnednullfor every failure, making rate-limits and server errors indistinguishable from "no price data". Two latent defects fixed:Unmapped symbols now throw
AugustValidationError(INVALID_INPUT) before any network call is made, avoiding a wasted round-trip with"undefined"in the URL.A 429 response now throws
AugustRateLimitError; any other non-2xx throwsAugustServerError. JSON parse errors and network-level failures continue to returnnull(unchanged).
4db12d7: chore: resolve biome and tsdoc lint warnings in
core/fetcher.tsandcore/helpers/core.ts— replaceanywithunknown/generics, use template literals andDate.now(), drop non-null assertions and unused catch bindings, and add the missing@paramhyphens. No behavior change.b9b59c4: fix: carry the deposit asset (
assetIn/decimals) through archived-vault history so mixed-decimal pre-deposit vaults compute lifetime PnL correctly. Without it, an 18-decimal deposit (e.g. USDS) into a 6-decimal-vault was normalized at the vault's decimals, inflating the cost basis ~1e12 and showing -100% / multi-billion PnL.50a29b4: fix: archived-vault user history now sorts ascending by timestamp (matching the subgraph path's ordering contract) and drops rows with an unparseable timestamp instead of emitting a "NaN" stamp
34dc7c6: fix: drop unused
@ts-expect-errorin Buffer polyfill; useglobalThiscast instead of bareglobal03ba56b: docs(readme): fix broken quick-start snippet and sub-accounts accessor in the package README
The
@augustdigital/sdkpackage README (rendered on npmjs.com and bundled in the tarball) used a named importimport { AugustSDK } from '@augustdigital/sdk', but the package only exposesAugustSDKas a default export — so the copy-pasted snippet resolved toundefinedandnew AugustSDK(...)threw. Switched to the default importimport AugustSDK from '@augustdigital/sdk'.Also corrected the Sub-Accounts section heading from
sdk.subaccounts(a private field) to the public accessorsdk.subAccountsModule.a8a9c74: fix: correct vault LP share-price math and
round()on bigintsfetchTokenPricecomputed a vault LP token's share price by integer-dividing the rawtotalAssets/totalSupplybigints, which floored a ~1.05 ratio to1and re-normalized it to ~1e-18 — collapsing the LP price to ~0 (and throwing on a zero-supply vault). Share price is now derived from the normalized values.round()threwTypeErrorwhen called on abigintwithout an options object, because the bigint branch readoptions.decimalsinstead ofoptions?.decimals. It now falls back to the default decimals as documented.
c2cfd5c: fix: correct current-TVL value, loan-cache staleness, and the musd CoinGecko price
getVaultTvl(current/non-historical path) returned the vault'stotalSupply()(shares minted) instead of assets under management. It now readsgetTotalAssets()(evm-2) /totalAssets()(v1), matching the historical path. TVL is no longer understated by the share-price ratio.fetchTokenizedVaultLoans/fetchTokenizedVaultSubaccountLoansread the shared LRU cache twice (if (CACHE.get(key)) loans = CACHE.get(key)). Because the cache allows stale reads and deletes a stale entry on firstget, a stale hit returnedundefinedinstead of refetching. They now usegetSafeCache/setSafeCache, which refetch on expiry like the rest of the SDK.fetchTokenPricesFromCoinGeckoreturned a nested tuple ([['…', 1]]) for themusd(mezo-usd) stablecoin while every other branch returns a scalar, yieldingNaN(or a non-number "price") downstream. It now returns the scalar peg1.
093f09d: fix(stellar): surface the decoded Soroban transaction result code on submit failures (AUGUST-6412)
submitStellarTransactionnow decodes the transaction-level XDR result-code discriminant (e.g.txBadSeq,txTooLate) and attaches it asresultCodeon both the thrownAugustSDKErrorcontext and the error log — on the send-timeERRORpath and the confirm-timeFAILEDpath. Previously the reason was only available buried inside the stringified XDR in the error message.Decoding is best-effort: if the RPC result is not a decoded union,
resultCodeis omitted (undefined) and the error still carries the stringified XDR, so the message text is unchanged. As a side effect of the refactor, the failure-detail guard changed from key-presence ('errorResult' in sendResult) to truthiness — a present-but-falsy result now yields an empty detail (the message falls back to the status) instead of the literal"null".No public API surface changes.
b57c70c: chore: resolve biome and tsdoc lint warnings in
modules/vaults/getters.tsandservices/coingecko/fetcher.ts— type thepoolTotalSupplylocals anddefiPerBorrower/renderStatus/CoinGecko response shapes instead ofany, initialize the redemption-date locals, drop non-null assertions, switch to optional chaining, and fix the@paramhyphens,{@link}throws tags, and a brace-laden@returns. No behavior change.
8.5.0
Integrator highlights
New: CROSS_CHAIN_VAULT_CONFIGS registry exports August LayerZero OVault deployments by address.
New: getCrossChainVaultConfig, isCrossChainVault, getOVaultChains, isHubOnlyReceipt, getWithdrawDestinationChains helpers resolve cross-chain vault configuration.
New: Pass ICrossChainVaultConfig directly to crossChainVaultDeposit and quoteCrossChainDeposit instead of assembling per-chain maps.
Full changelog
Minor Changes
621e098: feat(evm): add cross-chain OVault vault registry + resolver helpers
Adds an address-keyed registry (
CROSS_CHAIN_VAULT_CONFIGS) of August's LayerZero OVault deployments plusgetCrossChainVaultConfig,isCrossChainVault,getOVaultChains,isHubOnlyReceipt, andgetWithdrawDestinationChains. Consumers can now resolve a fullICrossChainVaultConfigby vault address — and pass it straight tocrossChainVaultDeposit/quoteCrossChainDeposit— instead of hand-assembling per-chain contract maps and LayerZero EIDs. Mirrors the SwapRouter registry pattern.
8.4.0
Integrator highlights
Action: Review
getVaultsbehavior — closed vaults are excluded by default; passincludeClosed: truefor portfolio/position-tracking use cases.New: New
AugustApibackend module withgetVaultUnrealizedPnlHistory()andgetLatestUnrealizedPnl()methods.New:
getVaultsnow accepts optionalincludeClosedflag to include closed vaults in results.New: Published type declarations now include full TSDoc and exclude
@internalhelpers from autocomplete.
Full changelog
Minor Changes
70e1792: feat: new
AugustApibackend module —sdk.apiModule(methods also exposed directly onAugustSDK) for backend-computed data with no on-chain equivalent:getVaultUnrealizedPnlHistory({ vault, limit? })— a vault's unrealized-PnL snapshot series, newest first.getLatestUnrealizedPnl()— the most recent unrealized-PnL snapshot for every tracked vault.
Both methods hit the public (unauthenticated) August API with exactly one HTTPS request and no RPC calls, validate inputs up front (
AugustValidationError), throw typed errors on HTTP failures and response-contract mismatches, and return camelCasedIUnrealizedPnlSnapshotobjects.8191dc7: feat:
getVaultsgains an opt-inincludeClosedflag for portfolio use. By defaultgetVaultsexcludes closed vaults, so marketplace/discovery callers never receive astatus: 'closed'vault and don't have to filter it out themselves. WhenincludeClosed: trueis passed, closed vaults are returned (regardless ofis_visible, since closed + invisible vaults bucket as closed) so a consumer joining user positions can render a position held in a closed vault. In that mode, loans/allocations enrichment is also skipped for closed vaults — they have none, andgetVaultAllocationsotherwise re-throws (no debank data / no subaccounts), which previously dropped the vault into thefailedbucket and silently removed it from the result. Additionally,includeClosednow propagates down to the per-vault EVM getter (getEvmVaultV1/getEvmVaultV2), which otherwise returnsnullfor anystatus: 'closed'+is_visible: falsevault ("skip closed staging vaults") — that null causedgetVaultto return null and the vault to vanish fromgetVaultseven with the closed bucket spread in. WithincludeClosed, closed + invisible vaults resolve their metadata. Active vaults are always fully enriched and unaffected.1e1d1b1: feat: trim
@internalhelpers from the published type surface and restore TSDoc in published declarationspackage.json#typesnow points at an api-extractor rollup (lib/sdk.d.ts) that omits every export tagged@internal(safeBigInt,safeSendTx,safeWaitForTx,tryRecoverTxHash,resolveSpender,validateAmountPrecision, and friends) so they no longer appear in integrator autocomplete or type resolution from the package root.The SDK build no longer strips comments from emitted output, so the published
.d.tscarries the full TSDoc — editors now show hover documentation for every public method.Runtime exports are unchanged and deep
lib/**imports still resolve; this is a types-surface change only.walletClientToSignerintentionally remains public until the viem-native signer path ships.CI fails if an
@internalexport reappears in the public types (scripts/check-internal-dts.mjs).
Patch Changes
db5a53a: fix: Phase-2 review hardening
@augustdigital/config: result-schemaaddressfields now accept Stellar (G…account /C…contract) addresses, matching the SDK and backend address contract — previously a Stellar vault passed input validation but failed output-schema validation with a misleadingSCHEMA_MISMATCH.@augustdigital/mcp: address validation now accepts StellarC…contract addresses (parity with the SDK'sisStellarAddress), and the HTTP transport compares bearer tokens in constant time viacrypto.timingSafeEqual.@augustdigital/sdk: the unrealized-PnL response guard validates every required snapshot field — including the numeric monetary fields — so backend contract drift throws a typedAugustServerErrorinstead of silently emittingundefinedPnL values.
8.3.0
Integrator highlights
Action: IStellarUserPosition gains optional
decimalsFromFallback?: boolean; callers sizing a redeem must refuse to settle when it istrue.Action: Stellar Soroban transactions now use a 10-minute validity window anchored to network time, reducing
txTOO_LATEerrors on slow signers.
Full changelog
Minor Changes
ee58832: feat(telemetry): forward SDK-internal logs to Sentry in production
initializeSentrynow bridges the SDK'sLoggerto the resolved Sentry SDK.Logger.log.erroris captured as a sanitized Sentry issue (the call-site label becomes thesdk.origintag; structured context becomes scope extras), andLogger.log.warnis recorded as awarning-level breadcrumb that rides along with the next captured event.Previously these were no-ops in production unless an integrator manually wired a logger, so the SDK's own diagnostics never reached the partner-usage dashboard. The bridge is installed only when analytics is enabled (it respects every existing disable path —
analytics.enabled: false,AUGUST_SDK_DISABLE_ANALYTICS, dev/testNODE_ENV, and localhost), never throws back into the caller, and is cleared byresetAnalytics(). The integrator-pluggableLogger.setLogger/Logger.setStructuredLoggerslots are unchanged.908c2c4: fix(stellar): anchor Soroban tx timebounds to the network clock and widen the validity window to 10 minutes (AUGUST-6386)
Stellar Soroban deposit/redeem transactions could fail with
txTOO_LATEafter signing.buildSorobanTxstamped the transaction'smaxTimefrom the signer's local clock via.setTimeout(120), so:a device clock lagging behind network time built an already-expired transaction, and
slow / asynchronous signing paths (hardware wallets, institutional approval flows) could not complete within the 120-second window.
Changes:
maxTimeis now anchored to the network clock.buildSorobanTxreads the latest ledger close time (getLatestLedger→getLedgers().latestLedgerCloseTime) and builds the tx withsetTimebounds(0, networkCloseTime + TX_TIMEOUT_SECONDS), immunizing the deadline against signer clock skew. The network read runs in parallel with the account fetch (no added latency) and falls back to the previous local-clocksetTimeoutwindow on any RPC failure, so it never regresses.TX_TIMEOUT_SECONDSraised from 120 to 600 (10 minutes) to cover slow/async signing while staying within the Soroban footprint/ledger-entry TTL.
No public API surface changes. The read-only
queryContractpath is unaffected.15a6fcf: fix(stellar): surface a
decimals()read failure ongetStellarUserPositioninstead of silently falling back to 7getStellarUserPositionreadsbalance()anddecimals()in parallel. Whendecimals()failed butbalance()succeeded, it returned a confident{ shares, decimals: 7 }indistinguishable from a genuine 7-decimal vault. A consumer sizing aredeemagainst an ERC4626 offset vault (share decimals = asset + offset, e.g. 13) would then under-redeem by10^offset— a silent money-correctness gap (AUGUST-6381, follow-up to AUGUST-6380).IStellarUserPositionnow carries an optionaldecimalsFromFallback?: boolean(optional for source back-compat — existing consumer object literals still compile — but always populated bygetStellarUserPosition). It istruewhendecimalsis the fallback (the on-chain read failed) andfalsewhen it is the authoritative on-chain value. Callers that size a redeem MUST refuse to settle when it istruerather than trustingdecimals. The SDK's owngetVaultPositionsnow treats a fallback-decimals position as a failed read and reports a zero balance instead of a mis-scaled one. No change to thenull-on-balance-failure behavior.
Patch Changes
d548100: chore: migrate tooling to Biome (lint + format) and add Knip (dead-code/unused-deps)
Replaces ESLint + Prettier + oxlint with Biome for linting and formatting, and adds Knip for unused-file/dependency detection (report-only baseline). A minimal ESLint config is retained solely to run
eslint-plugin-tsdoc(pnpm lint:tsdoc), which Biome has no equivalent for. Inline// eslint-disabledirectives that referenced now-Biome rules were translated to// biome-ignore/// biome-ignore-all. No runtime behavior or public API change.769c982: refactor(logging): route remaining console.* calls through Logger
Swept the last non-Solana
console.{log,warn,error}sites ontoLogger.log.{info,warn,error}, each tagged with its originating function:core/fetcher.ts,core/helpers/web3.ts,core/base.class.ts,adapters/sui/getters.ts, andmodules/vaults/fetcher.ts. Combined with the Logger→Sentry bridge, these diagnostics are now sanitized and (in production) forwarded to Sentry instead of leaking to the integrator's console.The
no-consoleESLint rule is tightened to flag every console method (previouslywarn/errorwere allowed). The logger module — the dev-mode floor (core/logger/index.ts) and the Slack transport (core/logger/slack.ts, which cannot importLoggerwithout a cycle) — is exempted, and a few deliberately integrator-facing notices (the version-update nudge and theoverridedeprecation warning) keepconsole.warnbehind documented inline exceptions.
8.2.0
Integrator highlights
Action: Indexers watching vaults now in
VAULTS_USING_SWAP_ROUTERmust also index SwapRouter events (Deposit,SwapExecuted, etc.) as vault-direct deposit events no longer fire.Action: Call
vaultDepositwithslippageBpsoption to override the default 1% slippage on SwapRouter-routed deposits.New:
EVMAdaptergainsswapAndDeposit,depositViaSwapRouter, anddepositNativeViaSwapRouterfor single-call swap-and-deposit flows.New: New
fetchSwapQuotefunction builds calldata for the SwapRouter swap leg; results includefetchedAtfor staleness detection.New: New
IContractWriteOptions.receiverlets callers mint vault shares to an address other thanwallet.
Full changelog
Minor Changes
0070001: feat: SwapRouter integration for vault deposits (AUGUST-5475).
Adds the on-chain
SwapRouterperiphery contract to the SDK so users can deposit any whitelisted ERC-20 (or native ETH) into any opted-in August vault via a single atomic call. The SwapRouter swaps the input to the vault's reference asset and forwards the proceeds to the vault's deposit interface, normalizing ERC-4626 (v1/v3) and multi-asset (v2) flows behind one entry point.New public surface
New methods on
EVMAdapter:swapAndDeposit,depositViaSwapRouter,depositNativeViaSwapRouter(all inmodules/vaults/write.actions.ts). Each handles approval automatically against the SwapRouter as spender and returns the resulting tx hash.New public function
fetchSwapQuoteinservices/swap-quotesbuilds the calldata needed for a SwapRouter swap leg. v1 uses Paraswap; the result is shaped so 1inch/0x can be added later without breaking callers. Results includefetchedAtso UI integrators can detect stale quotes.vaultDepositnow routes through the SwapRouter automatically when the target vault is inVAULTS_USING_SWAP_ROUTERand the chain has a registered router. The existing call signature is unchanged. New optionalIContractWriteOptions.receiverlets callers mint shares to a different address thanwallet(treasury / cold-storage flows).New per-chain constants:
SWAP_ROUTER_ADDRESSES(Ethereum mainnet:0xAC771209FF2b71EECfF6E85a9AD01db8Ff2618B0),SWAP_ROUTER_WRAPPED_NATIVE(mainnet: WETH), andSWAP_ROUTER_MAX_SWAPS(mirrors the on-chainMAX_SWAPS = 9). New vault opt-in setVAULTS_USING_SWAP_ROUTERandORIGIN_CODESregistry for partner/referral fee tracking.New types:
ISwapParams,ISwapAndDepositOptions,ISwapRouterDirectDepositOptions,ISwapRouterNativeDepositOptions,SwapRouterVaultType(values1for ERC-4626,2for TokenizedVaultV2 — mirrors the on-chain constants).New ABI
ABI_SWAP_ROUTER.
Safety hardening (vs. naive integration)
Per-leg
ISwapParamsvalidation rejectsamountIn === 0n,minAmountOut === 0n(slippage off),tokenIn === tokenOut, malformed router/payload at the SDK boundary.slippageBpsaccepts[0, 10_000)—10_000(100% slippage = no protection) is rejected.originCodemust be a 32-byte hex string; the SDK throws a typedAugustValidationErrorinstead of waiting for the on-chainInvalidOriginrevert.Paraswap response shape is validated end-to-end:
priceRoute.destAmountmust be a numeric string,tomust be a valid address,datamust be hex calldata with at least a 4-byte selector.Vaults in
VAULTS_USING_SWAP_ROUTERcannot silently fall through to the legacy adapter path. If the chain has no SwapRouter deployed, orchainIdcannot be resolved, the SDK throwsAugustValidationError('INVALID_CHAIN')— never routes through the MEV-vulnerable legacyminAmountOut: 0path.isDepositWithPermit: trueon a SwapRouter-routed vault throws rather than silently dropping the permit signature.Native ETH deposits target only vaults whose reference asset equals the chain's wrapped-native token; other configurations throw with actionable guidance.
swapAndDepositstrictly requiressigner.getAddress()to return a valid EOA (no silent fallback to receiver). Smart-account integrators (Safe, ERC-4337) should be aware that the SwapRouter pulls frommsg.sender, not the controlling EOA — for those flows the SDK currently expects the smart account itself to be the signer's address.Paraswap quote fetches accept an optional
AbortSignalfor cancellation/timeout.
Coexistence with legacy adapters
Legacy adapter paths (Treehouse, Kelp, AVAX native, Paraswap
UniversalAdapterfor non-opted-in vaults) continue to work unchanged. The two systems coexist; vaults will converge onto the SwapRouter in follow-up PRs.Deployment checklist (operator)
Before adding a vault to
VAULTS_USING_SWAP_ROUTER, the contract owner must complete the following on the SwapRouter (0xAC77…18B0on mainnet):enableVault(vaultAddr, vaultType, swapFee)— register the vault with the correctvaultType(1 for ERC-4626, 2 for TokenizedVaultV2) and any per-vault swap fee in bps.enableToken(token)— per accepted input token (e.g. WBTC, cbBTC, tBTC for the BTC v2 vault).enableRouter(routerAddr, tokenApprovalAddr, authorizedSelector)— per DEX router the quote provider may target. Paraswap's "augustor" address is set per chain; the approval-target (TokenTransferProxy) and the selectors used by/transactionsare admin inputs.For non-default origin codes,
addOrigin(originCode, originFee, originFeeCollector).For v2 multi-asset vaults: add the SwapRouter to the vault's sender whitelist.
The forknet smoke test at
tests/vaults/forknet-swap-router-abi.test.jsreadsvaultInfo,whitelistedTokens, and the contract constants from the deployed router and fails if any expected vault is unregistered. Runpnpm test:forknetto verify before release.Behavior change for indexers
For vaults moved to the SwapRouter, deposits no longer emit from the vault contract directly — events are emitted by the SwapRouter (
Deposit,SwapExecuted,SwapFeeApplied,OriginFeeApplied). Subgraphs that index the vault's deposit events for the BTC v2 vault should be updated to also index the SwapRouter.
Patch Changes
7d4f38f: fix: sync
VAULTS_USING_SWAP_ROUTERwith on-chainenableVaultstate on the mainnet SwapRouter (0xAC771209FF2b71EECfF6E85a9AD01db8Ff2618B0).The set previously listed
0x8AcA0841…362C21(uptBTC) as a placeholder, but noVaultEnabledevent was ever emitted for that address —vaultUsesSwapRouterwas reportingtruefor a vault that the on-chain router would reject withInvalidVaultat deposit time.Replaces the set with the two vaults currently registered on the contract:
0xE9B725010A9E419412ed67d0fA5f3A5f40159D32— Upshift Core USDC (vaultType=1, ERC-4626, reference asset USDC).0x74aD2F789Ed583DBd141bbdafC673fE1F033718b— Sentora USD (vaultType=2, Tokenized Vault V2, reference asset USDC).
Verified via
vaultInfo(addr)reads and the fullVaultEnabledevent log on the deployed router. Consumers gated onvaultUsesSwapRouter(notablyvaultDepositdispatch) will now route the two registered vaults through the SwapRouter and continue to fall back to the legacy adapter path for everything else.ea679fc: fix: SwapRouter dispatch now reads the underlying asset's on-chain decimals when fetching a swap quote (previously reused the vault share-token decimals, which diverge for multi-asset v2 vaults — e.g. the 18-decimal share over the 8-decimal WBTC reference asset on the BTC v2 vault — and yielded a mispriced Paraswap quote).
fix: Paraswap calldata now embeds the slippage-adjusted minimum
destAmountso the aggregator's own min-out check matches the SwapRouter'sminAmountOut. Previously the calldata was built with the exact priceRoutedestAmount(0% tolerance) and the DEX leg would revert on any adverse movement before the SwapRouter's slippage check could apply.feat:
IContractWriteOptions.slippageBpslets callers ofvaultDepositoverride the default 1% slippage tolerance applied on SwapRouter-routed deposits that require a swap.5242f18: fix: honor
IContractWriteOptions.receiveron the SwapRouter swap-and-deposit pathvaultDepositdispatched through the SwapRouter was passingwalletas the share recipient on the swap leg, ignoring an explicitreceiveroverride. The direct-deposit and native-deposit paths already honored it; the swap path now matches.
8.1.0
Integrator highlights
Breaking: Result record from
getHealthFactorOfBorrowersByVaultis now keyed by lowercased vault address; lookups using mixed-case addresses will miss.Action: Update vault-address lookup keys to use
address.toLowerCase()when reading health-factor results.New:
AugustSDK.getVaultBorrowerHealthFactoraccepts an optionalvaultfield to scope the fetch to a single vault.New: New exported type
IVaultBorrowerHealthFactorreplaces the previous inline result shape.
Full changelog
Minor Changes
bc5d468: feat:
getVaultBorrowerHealthFactoris now vault-scopable and resilient to per-loan failures.New optional
vaultfield onAugustSDK.getVaultBorrowerHealthFactor({ chainId, vault })(and matching positional param onAugustVaults.getVaultBorrowerHealthFactor). When provided, only that vault's tokenized record is fetched and only its loans are walked — the all-vaults / all-chains fanout is skipped entirely.Internal
getVaultBorrowerHealthFactor({ vault, options })andgetHealthFactorOfBorrowersByVault({ options, vault? })(both inmodules/vaults/getters.ts) now usePromise.allSettledfor the loan-state / borrower / per-vault iterations. A single bad loan contract (e.g. a test loan whose address isn't a real deployed contract, or whoseloanState()reverts) drops that row from the result and is logged viaLogger.log.warninstead of rejecting the whole batch. Same applies to the per-borrower August backend call.The
Record<vault, …>returned bygetHealthFactorOfBorrowersByVaultis now keyed by lowercased vault address. Callers must look entries up withaddress.toLowerCase(). The previous keys reflected whatever casing the upstream/public/tokenized_vault/endpoint returned, which silently caused lookups againstgetAddress(pool)to miss.New exported type
IVaultBorrowerHealthFactorreplaces the previous inline{ borrower, loan, health_factor? }shape.
Closes the upshift-app issue where the Allocation Breakdown HF column would render a perpetual loading skeleton on Upshift USDC because one bad test loan's RPC call sank the entire health-factor batch (AUGUST-6291).
8.0.0
Integrator highlights
Breaking:
StellarNetworktype alias is removed; switch toIStellarNetwork.Breaking: Constructor
keys.octavfifield is removed; passing it was always a no-op.
Full changelog
Major Changes
ebeb2c6: chore: remove two unused symbols from the published type surface — the
@deprecated StellarNetworkalias (useIStellarNetworkinstead; the alias existed for back-compat and has 0 internal consumers across our repos) and theoctavfi?: stringfield on the SDK constructor'skeysconfig (the field was never read; the octavfi service uses a hardcoded API key, not this config). No runtime behavior changes. Consumers that referencedStellarNetworkshould switch toIStellarNetwork; consumers that passedkeys.octavfican drop it — it was a no-op.
Patch Changes
66b18f2: fix:
fetchTokenPricesFromCoinGeckonow returns the latest price on the success path. The previousif (data && data.length)guard checked thelengthproperty on an object response ({ prices, market_caps, total_volumes }) and silently collapsed every successful response tonull— only the hardcodedmusdshort-circuit was returning a real value. Fixes defect #1 fromtodo/32-coingecko-fetcher-defects.md; defects #2 (typed errors on non-2xx) and #3 (up-front symbol validation) remain pending.175da88: fix:
fetchVaultsBatchno longer mis-routes successful fetches that resolve to a falsy value (0,'',0n,null,false) into the failed pile. The success/failure branch now keys onresult.successonly, respecting the function's documented contract thatdatais the source of truth whensuccess === true.10b3b85: fix: break circular dependency
core/index.ts → core/auth → core/fetcher.ts → services/coingecko/fetcher.ts → core/index.tsby importingLoggerfrom thecore/loggerleaf module inservices/coingecko/fetcher.tsinstead of thecorebarrel. Restores the zero-cycle invariant enforced by theCircular Dependency CheckCI job.66b18f2: chore: route all
console.*calls underpackages/sdk/src.ts/services/(coingecko, debank, octavfi, subgraph) throughLogger.log.{info,error}. Each call is now tagged with the originating function name and carries structured context (status, statusText, pool, address, etc.) instead of the previous raw, unsanitized strings. Errors now flow throughsanitizeErrorbefore reaching Sentry, and dashboards can group by function tag rather than by error-message text. A newtests/services/services-logger-hygiene.test.tsregression-tests the floor: noconsole.*inservices/.
7.0.1
Integrator highlights
Breaking:
explorerLinkreturn type is restored tostring; code relying on the briefstring | undefinedshape from 7.0.0 should remove undefined guards.
Full changelog
Patch Changes
ddbfa62: fix: restore
explorerLinkreturn type tostring(regression in 7.0.0)The circular-dependency cleanup unintentionally tightened
explorerLink's return type tostring | undefinedby surfacing a branch that was previously masked bystrictNullChecks: false. Consumers had always compiled againststringvia the emitted.d.ts. Restore the historical public shape by returning''whenchainis falsy or unknown.
7.0.0
Integrator highlights
Breaking: Write helpers now throw
AugustValidationError/AugustSDKErrorinstead of returningundefinedor throwing plainError; callers must usetry/catchand narrow on these types.Breaking:
handleSolanaDepositandhandleSolanaRedeemnow throw on failure instead of returningnull; replace null-return checks withtry/catch.Breaking: Solana/Stellar adapters now throw
AugustValidationErrorfor input validation failures; existing plain-Errormessage-string matches will break.Action: Cross-chain: call
isQuoteStale(quote)before submitting a cross-chain deposit/redeem and re-quote when it returnstrue;quotedAt/expiresAtare now populated.Action: Solana deposit/redeem
depositAmount/redeemSharesnow acceptbigintfor raw on-chain units; preferbigintfor money flows to avoid float precision loss.
Full changelog
Major Changes
7ede403: fix(audit): correctness, validation, and observability hardening across deposit / withdraw / redeem flows
Breaking — write helpers now throw
AugustValidationErroron bad input andAugustSDKErroron downstream failures (previously returnedundefinedor threw a plainError). Callers that depended on the silent no-op or were matching onErrormessage strings need to wrap calls intry/catchand narrow onAugustValidationError/AugustSDKError.Breaking —
handleSolanaDepositandhandleSolanaRedeem(the Solana adapter'svaultDeposit/vaultRedeem) nowthrowon failure instead of returningnull. Callers checking for anullreturn must convert totry/catch.EVM
write.actionsvaultDeposit: amount is now encoded against the deposit token's decimals (not the vault's share decimals). Fixes a silent mis-scaling on EVM-2 multi-asset vaults and any native-token deposit into a vault whose share decimals ≠ 18. Native deposits always use 18 decimals.
vaultApprove: now mirrors
vaultDeposit's routing — picks the wrapper as spender for adapter deposits and the vault for multi-asset / standard deposits. Compares the existing on-chain allowance against the required amount (was: only re-approved when allowance was exactly0).vaultRequestRedeem: receipt-token approval now goes through
safeSendTxso Monad-style RPCs that return malformed pending-tx fields don't throw during parsing.vaultRedeem (dated-claim flow) and rwaRedeemAsset: both now use
safeSendTx+tryRecoverTxHashfor nonce-fallback parity withvaultDeposit/vaultRequestRedeem.rwaRedeemAsset: doc fix — the vault share must be approved to the subaccount, not the redeemable (output) asset. Caller responsibility unchanged; the comment was wrong.
All write helpers (
vaultApprove,vaultDeposit,vaultRequestRedeem,vaultRedeem,depositNative,rwaRedeemAsset) now throwAugustValidationErroron invalid wallet/target/wrapper addresses or missing required inputs, and reject JSnumberamounts that exceedNumber.MAX_SAFE_INTEGER.vaultDepositandvaultRequestRedeemnow requireamount(previously silently encoded as0viatoNormalizedBn(undefined)).vaultDepositthrowsAugustValidationErrorwhendepositAssetdiffers from the vault's underlying but no adapter is configured for the vault (previously fell through to a cryptic on-chain revert).vaultDepositandvaultRequestRedeemalways wait for the ERC-20 approval receipt before sending the deposit/redeem tx, regardless of the caller'swaitflag — closes a race window where a follow-up tx could be re-ordered ahead of the approval on some RPCs.Downstream tx failures (e.g. on-chain reverts) are now wrapped in
AugustSDKErrorwith the original error preserved oncauseand a structuredcontextpayload, instead of a plainError("Deposit failed: …").safeBigIntallowance read insidevaultDepositnow passes a'vaultDeposit:allowance'context so flaky-RPC warnings are discriminable from approve-path warnings.safeBigInt: emits a
Logger.warnon malformed RPC responses (e.g. bare"0x") so flaky RPCs don't cause silent gas waste from spurious approvals.
EVM cross-chain (
crossChainVault)crossChainVaultDeposit: now rejects unsupported user chains up front with a clear error (was: cryptic config-lookup or gas-estimation revert).
approveCrossChain: throws when the approval receipt reports
reverted(was: returned the hash unconditionally).Monkey-patch lock: timing out now throws instead of silently proceeding with conflicting concurrent patches.
Fee patch: warns via
Logger.warnwhen the LayerZero SDK returns an unexpectedcontractFunctionName, so the in-place LZ-fee buffer being silently no-op'd is visible in telemetry.TSDoc on
crossChainVaultDeposit,crossChainVaultRedeem,buildCrossChainVaultTx, andneedsCrossChainApprovalnow states the default slippage / fee / gas buffers and documents the "approval needed on RPC failure" defensive behavior.
Solana
handleSolanaRedeem: replaced
parseIntwith the newuiAmountToRawBnBN-based helper. Fixes precision loss for any 18-decimal mint above a few thousandths or any 9-decimal mint above ~9M tokens.handleSolanaDeposit: now uses the same helper for consistency.
Both handlers now throw
AugustValidationError/AugustSDKErroron failure instead of returningnull, matching the EVM helpers' error contract.
Stellar
submitStellarTransaction: polling now backs off geometrically (1.5x, capped at 8s) instead of fixed 2s — same worst-case ceiling on attempts, lower RPC pressure on long waits.
handleStellarRedeemTSDoc now documents the exact Soroban contract interface it assumes (redeem(shares: i128, receiver, owner, operator)).
Telemetry
rwaRedeemAssetis now classified underwrite.redeeminMETHOD_CATEGORIES(previously fell back to'unknown').
New exports
uiAmountToRawBn(fromadapters/solana/utils).resolveDepositTokenDecimals,resolveSpender,validateAmountPrecision,safeBigInt,safeSendTx,safeWaitForTx,tryRecoverTxHash,isNonceParsingfrommodules/vaults/write.actions(marked@internal— exported for unit testing).New polling constants:
POLL_INTERVAL_MAX_MS,POLL_INTERVAL_BACKOFF.
Minor Changes
ae03a7b: feat(sdk): new
approvemethod returns a discriminatedApproveResultAdds
augustSdk.evm.approve(...)(and the underlyingapproveexport frommodules/vaults/write.actions) that returns one of:Lets callers tell apart "we sent a tx", "existing allowance already covers the amount", and "the resolved deposit asset is native (msg.value, no allowance applies)" without re-reading on-chain state.
vaultApproveis unchanged — samePromise<string | undefined>shape, same spender routing, same allowance / native short-circuits. Both functions share the routing implementation via an internal helper so behavior stays identical.Method-taxonomy entry
approve → write.approveadded so Sentry rolls the new method up next tovaultApprove.dee70e0: feat(AUG-6139): partner-usage telemetry — isomorphic Sentry bootstrap, method taxonomy, dimension tags, and arg-shape capture
Node + browser Sentry resolved at runtime (
@sentry/nodeadded alongside@sentry/browser); CLI now emits telemetry from its top-level error handler.Every method span carries
sdk.category,sdk.chain, andsdk.argShapeso dashboards can slice partner usage by intent, chain, and call shape without leaking values.Fallback
partner.id = 'unverified:<appName>'andpartner.tier = 'unverified'tags ship until the verified-partner endpoint exists.setMeasurement('sdk.method.invocation' | 'sdk.method.error', …)adds counter-style aggregates for sum-based dashboards.New public exports:
getSentrySDK,getSentryRuntime,getMethodCategory,METHOD_CATEGORIES,chainIdToTagValue,computeArgShape,captureSdkException.
ae03a7b: feat(sdk): preview / allowance / balance / maxDeposit read helpers on the EVM adapter
Adds five additive read methods to
augustSdk.evmso consumers can stop reaching into raw ABIs for the most common vault reads:previewDeposit({ vault, amount, asset? })— shares returned by a deposit. Routes EVM-1 vaults toIERC4626.previewDeposit(uint256)and EVM-2 multi- asset vaults topreviewDeposit(address, uint256)(returns the share slot of the tuple).previewRedeem({ vault, shares })— assets returned by a redeem. Routes EVM-1 vaults toIERC4626.previewRedeem(uint256)and EVM-2 topreviewRedemption(uint256, false)(gross slot).allowance({ vault, owner, asset? })— raw ERC-20 allowance the owner has granted the vault. Whenassetis omitted the SDK resolves the vault's underlying viaIERC4626.asset().balanceOf({ asset, owner })— raw ERC-20 balance.maxDeposit({ vault, receiver? })— vault deposit cap. EVM-2 multi-asset vaults resolve viamaxDepositAmount(); EVM-1 vaults usemaxDeposit(receiver)with a zero-address default.
All helpers return a raw
bigintso BigInt math stays precise. Existing helpers (vaultAllowance,previewRedemption) are unchanged.Notes:
These methods require a signer because they live on
EVMAdapter, matching the existing read pattern (vaultAllowance,sendersWhitelistAddress, etc.). A read-onlyJsonRpcProviderwrapped viaWallet.createRandom().connect(provider)works for query-only use.Method-taxonomy entries (
previewDeposit,previewRedeem,allowance,balanceOf,maxDeposit) added so Sentry rolls them up correctly.Benchmarks for these helpers are deferred — they need a signer plumbed into
packages/sdk/benchmarks/suites/sdk-methods.js; unit tests with mocked contracts cover the routing and validation paths.
ae03a7b: feat(sdk): constructor option
timeoutMsoverrides the request timeout defaultAdds an additive
timeoutMsoption to theAugustSDKconstructor (via the sharedIAugustBaseconfig) that overrides the default request timeout used by every August fetcher helper. The compiled-in default (90 s) is preserved when the option is omitted; per-callIFetchAugustOptions.timeoutMsstill wins over the SDK-level default.Also exports two helpers for advanced use:
setSdkRequestTimeout(ms | null)— apply / clear the override directly.getSdkRequestTimeout()— read the active default (override or compiled-in).
Notes:
This is process-global state. If you instantiate multiple
AugustSDKobjects in the same process with different timeouts, the last constructor call wins.Lowering the default for the entire package was deliberately skipped — that change is behaviorally observable for current integrators and belongs on a major bump.
e3d589e: feat(audit-followup): tx-flow audit fixes — Solana bigint amounts, cross-chain destination validation, quote staleness, Stellar account error
Additive correctness improvements identified during the deposit / withdraw / redeem audit. No new exported types are renamed or removed.
Solana (
adapters/solana)handleSolanaDeposit/handleSolanaRedeemnow acceptbigintfordepositAmount/redeemShares, in addition to the existingnumberform. Whenbigintis passed it is treated as the raw on-chain unit and used directly — nouiAmountToRawBnround-trip through a JS float. Recommended for money flows so the value the wallet signs cannot drift from the value the UI displayed. Thenumberform is still supported for back-compat.The SDK wrapper methods
augustSdk.solana.vaultDepositandvaultRedeemwiden theirdepositAmount/redeemSharesparameter tonumber | bigintaccordingly.Both handlers reject
0n(and0) viaAugustValidationError.
Cross-chain (
evm/methods/crossChainVault)buildCrossChainVaultTxnow rejects requests wheredestinationChainIdoruserChainId(onDEPOSIT) is neither the configuredhubChainIdnor present inconfig.layerZeroEids.spokes. Previously the unknown chain ID silently fell back to the hub EID, routing user funds to a chain they did not pick. Behavior unchanged when the chain ID is omitted / equals the hub / is a configured spoke.quoteCrossChainDeposit/quoteCrossChainRedeemnow populatequotedAtandexpiresAton the returnedIQuoteCrossChainResult. The UI should callisQuoteStale(quote)before submit and re-quote when it returnstrue— LayerZero fees drift between quote and submit.New exports from
evm/types/crossChain:CROSS_CHAIN_QUOTE_TTL_MS(30 000 ms default validity window).isQuoteStale(quote, now?)helper.
Stellar (
adapters/stellar/soroban)buildSorobanTxnow wrapsserver.getAccountfailures: when the account does not exist or is unfunded, the SDK throws anAugustValidationErrorwith copy that names the actual fix ("send at least 1 XLM to activate"). Detected via bothinstanceof NotFoundError(forward-compat) and the current"Account not found: <addr>"message the rpc server actually throws. Other RPC errors propagate unchanged.
Known limitations (deferred)
The Solana
depositinstruction's IDL does not yet accept amin_shares_outargument, so client-side slippage protection cannot be enforced on-chain for Solana vaults. ATODO(slippage)comment marks the call site invault.actions.ts; on-chain enforcement requires a program update.
Patch Changes
a18ea6d: chore(benchmarks): per-iteration RPC/API request counting
Adds
benchmarks/request-counter.js, aglobalThis.fetchwrapper that buckets requests asrpc(Alchemy, Helius, QuickNode, etc.) vsapi(everything else, with a per-host breakdown). The harness now resets the counter before each measured iteration and surfacesmeanRpc,meanApi,meanRequests, and ahostBreakdownon every result.Console + markdown reporters render the new columns when counts are present and append a "Total requests across all measured iterations" section so AUGUST-5835-style perf claims (in-flight dedup, whitelist cache,
parallelLimitfix) can be measured directly instead of estimated from the diff.Counting is on by default. Set
BENCHMARK_ALCHEMY_REQUEST_COUNT=0to skip the global fetch patch (e.g. in environments where another tool already wrapsfetch). No behavior change to the SDK itself — this is a benchmark-tooling-only change.0f92c9c: refactor(vaults/date-utils): lift duplicate
TIMESTAMP_MANIPULATION_WINDOW = 300to module scopecomputeClaimableDateandisClaimableNoweach re-declared the sameconst TIMESTAMP_MANIPULATION_WINDOW = 300inside their function bodies. Lifted to a single module-level constant mirroringTimelockedVault.sol's 5-minute window. Pure refactor — identical observable behavior.Coverage was thin (no existing tests for
date-utils.ts); addstests/vaults/date-utils.test.tscoveringcomputeClaimableDate,isClaimableNow,formatDateKey,isValidClaimableDate, andgetDaysInMonth(8 tests, including UTC-day rollover and leap-February).0f92c9c: perf(adapters/evm): parallelize receipt-token + whitelisted-assets fetch in
getEvmVaultV2After the initial vault-contract
Promise.allresolves,getEvmVaultV2previously fetched the receipt-token metadata batch (5 RPCs) and the whitelisted-assets list (1 RPC) sequentially, even though both depend only onvaultContractCallsand have no data dependency on each other. They now run inside a shared outerPromise.all, so the wall time per V2 vault read is bounded by the slower of the two batches instead of their sum.No change to the merged
combinedCalls/combinedFunctionsshape, so downstreambuildFormattedVaultsees identical inputs. Static regression test (tests/adapters/evm-vault-v2-parallel-fetch.test.ts) guards the wrapping pattern.0f92c9c: docs(adapters/evm): TSDoc for
vaultAllowance,vaultDeposit,vaultRequestRedeem,depositNative, andvaultRedeemThe EVM adapter's public write methods shipped without TSDoc blocks, which CLAUDE.md section 1 requires for every exported symbol on the published surface. Integrators saw "(no description)" in their IDE and had to read
modules/vaults/write.actions.tsto learn the parameter shape and return semantics. Each method now has a one-sentence summary,@param/@returns/@throwsnotes, and an@example. A static presence test (tests/adapters/evm-write-tsdoc.test.ts) guards against regression.No behavior change.
0f92c9c: refactor(vaults/utils): extract local
IEvmAssetMetadatatypebuildFormattedVaultdeclared the same{ address: IAddress; symbol: string; decimals: number }shape twice as inline types (once fordepositAssets[], once forreceipt). Lifted to a single file-local@internaltypeIEvmAssetMetadata. Not exported — kept internal so the public surface doesn't grow. Pure refactor.0f92c9c: perf(core/web3): in-flight request dedup for
getDecimalsandgetSymbolgetDecimalsandgetSymbolalready cache results in the sharedlru-cache, but concurrent identical calls (e.g. a fresh page-load with multiple components asking for the same token's decimals before any cache write lands) each fired their own RPC. The price-fetcher path already used an in-flightMap<key, Promise>to coalesce these —PRICE_REQUESTSincore/fetcher.ts:250— and this change applies the same pattern togetDecimals(DECIMALS_REQUESTS) andgetSymbol(SYMBOL_REQUESTS).Behavior on a cold cache: the first caller initiates the RPC; subsequent callers within the same tick share that promise instead of starting their own. On error, the in-flight entry is cleared in a
finallyso the next caller can retry. Cache-hit and Solana-address fast paths are unchanged, so no observable difference for callers that aren't concurrent.Adds
tests/utils/getdecimals-getsymbol-dedup.test.tswith three cases (coalescing, no-false-coalescing across addresses, getSymbol parity).0f92c9c: perf(core/web3): in-flight request dedup for
getReceiptTokenAddressgetReceiptTokenAddressalready caches results in the sharedlru-cache, but concurrent identical reads (multiple components or vault paths resolving the same vault's receipt-token address before the first cache write lands) each fired their ownlpTokenAddress()RPC. This change adds aRECEIPT_TOKEN_REQUESTSin-flightMap<string, Promise>so simultaneous identical reads share a single promise — same pattern as the existingDECIMALS_REQUESTS,SYMBOL_REQUESTS, andWHITELISTED_ASSETS_REQUESTSmaps. The in-flight entry is cleared in afinallyso the next caller can retry after a failure.Cache-hit and missing-arg fast paths are unchanged.
Adds
tests/utils/getreceipttokenaddress-dedup.test.ts(coalescing + no false-coalescing across addresses).0f92c9c: perf(vaults/getters): lift duplicate
getReceiptTokenAddresscall in the V2 position-read pathInside the
version === 'evm-2'branch of the position loop inmodules/vaults/getters.ts,getReceiptTokenAddress(provider, vault)was awaited twice for the same vault in back-to-back lines — once to derive decimals, once again to construct the receipt contract for the balance read. The second call was a cache hit (so cheap in RPC terms) but still incurred a function call, a cache lookup, and a Promise hop per iteration. Both call sites now reuse a singlereceiptAddresslocal.Pure lift with no behavior change — same value returned in both spots either way, and the wallet-balance branch only runs when the first await would also have run.
ae03a7b: fix(adapters): Solana / Stellar adapters now throw typed errors for input validation
Replaces every
throw new Error(...)in the Solana and Stellar adapter paths that represents an input-validation failure withAugustValidationError, and the Stellar submit / Soroban downstream failures withAugustSDKError/AugustTimeoutError. Consumers can now narrow:…on non-EVM paths, just like EVM. Error messages are unchanged, so existing substring assertions and Sentry message-based grouping continue to work; the class-based bucket gains signal.
Affected files:
adapters/stellar/actions.ts—validateContractAddress,validateAccountAddressadapters/stellar/soroban.ts—toBigIntAmount, simulation / assembly failures (nowAugustSDKError)adapters/stellar/submit.ts— submission failures (AugustSDKError), poll-timeout (AugustTimeoutError)adapters/stellar/getters.ts—getStellarUserPosition/convertToSharesaddress validatorsadapters/stellar/utils.ts—assertNotStellar(nowINVALID_CHAIN)adapters/solana/vault.actions.ts— input-validation failures insidehandleSolanaDeposit/handleSolanaRedeemadapters/solana/utils.ts— wallet / program-id / vault-version validation anduiAmountToRawBnprecision checks
bb0873f: fix(perf-pr-review): address review findings on the perf-optimizations PR
Bundle of small fixes responding to the code review of
AUGUST-5835-perf-optimizations. No public-API change.CACHE.hasvsCACHE.gettruthy check — flipped 4 sites incore/helpers/web3.ts(getDecimals,getSymbol,getReceiptTokenAddress,getWhitelistedAssets) fromif (CACHE.get(key))toif (CACHE.has(key)). Tokens withdecimals === 0, empty-string symbols, or empty whitelist arrays were silently re-fetching on every sequential call because the cached value was falsy. Resolves and supersedestodo/29.getWhitelistedAssetstyped error — replacedthrow new Error(...)withAugustValidationError('INVALID_INPUT', ...). The function stays@internal; the change keeps Sentry's error-grouping intact (rawErrorcollapsed to the generic bucket).generatePermitSignatureLogger — theconsole.error('Could not fetch DOMAIN_SEPARATOR…')that the Solana sweep had skipped is nowLogger.log.error('generatePermitSignature', error, { message: … }), with the original throw preserved.Dead
namewrite — movedlet nameinto the cache-miss discovery block (const name = …). The assignment on the cache-hit path was never read;signTypedDatausesmatchingDomaindirectly.runWithConcurrencycorrectness note — one-line comment explaining whynextIndex++is safe across workers (JS single-threaded; increment finishes before anyawait).Parallel-fetch test upgrade —
tests/adapters/evm-vault-v2-parallel-fetch.test.tsis rewritten from a regex-on-source assertion to a behavior test that mocksContract/getDecimals/getSymbol/getWhitelistedAssetswith controlled delays and asserts wall time falls in the parallel range (1.5×–2.5× RPC_DELAY), not the serial range (3× RPC_DELAY).New regression test —
tests/utils/cache-falsy-value-hit.test.tsprovesgetDecimalsreturning0is cached and the second call doesn't re-fetch.
0f92c9c: perf(vaults/utils): cache matched permit domain per (chainId, token)
generatePermitSignaturepreviously, on every invocation, fetched the token'sname()(RPC), built 4 candidate EIP-2612 domain configurations, hashed each withTypedDataEncoder.hashDomain, and — only if all 4 failed — fell back to fetchingversion()(another RPC). For integrators generating multiple permits against the same token in a session, every signature reran the full discovery.The matched
TypedDataDomainis now cached in the SDK's sharedlru-cachekeyedpermit-domain-<chainId>-<token>for 1 hour. The liveDOMAIN_SEPARATOR()is still fetched on every call and compared against the cached domain's hash; on mismatch (e.g. an upgraded token contract) the cache entry is invalidated and the original discovery loop runs. On a cache hit thename()RPC, the 4-iteration hashing loop, and the rareversion()fallback are all skipped.The function also pairs
nonces()withDOMAIN_SEPARATOR()in a singlePromise.all(they were previously sequential), shaving a round trip on the cache-miss path.Adds
tests/vaults/permit-domain-cache.test.tscovering the discovery path and the cached fast-path.0f92c9c: refactor(adapters/solana): route console.* through Logger
Replaces all 50 raw
console.log/console.warn/console.errorcalls inadapters/solana/{vault.actions,utils}.tswith the equivalentLogger.log.{info,warn,error}calls. Output is now sanitized via the analytics pipeline and gated byLogger.setDevMode()/Logger.setStructuredLogger()rather than being printed unconditionally to stdout. Level mapping is preserved (console.log→info,console.warn→warn,console.error→error). No behavior change for callers that have not configured a logger; consumers that have already enabled dev mode or plugged in a structured logger will now receive Solana adapter events on the same channel as the rest of the SDK. A static test (tests/adapters/solana-logger-hygiene.test.ts) guards against regression.a18ea6d: fix(adapters/solana): propagate the underlying error from
getVaultMintsinstead of swallowing itSolanaUtils.getVaultMintspreviously caught any failure insideprogram.account.vaultState.fetch(vaultStatePda)— Anchor discriminator mismatch, account-not-found, RPC error — logged it, and returned{ depositMint: '', shareMint: '', vaultVersion: undefined }. DownstreamhandleSolanaDeposit/handleSolanaRedeemchecked the empty mints and threw the generic"Failed to read vault mints from on-chain state", which carried zero diagnostic signal. Operators triaging a failed deposit on a specific vault (e.g. Sentora xBTC on the Upshift portfolio page) had nothing actionable in the user-visible error.getVaultMintsnow throws anAugustSDKError(code: 'UNKNOWN') whosemessageincludes the underlying cause and whosecontextcarriesvaultProgramIdandvaultAddress. The original error is set as.cause. Successful reads still cache as before; the existing read-sidegetVaultStateReadOnlypath is unchanged.The outer catch in
handleSolanaDepositalready re-wraps SDK errors withcause, so the user-visible message becomes"Solana deposit failed: Failed to read vault mints from on-chain state: <real cause>"— pointing at whether the IDL is wrong, the PDA doesn't exist, or the RPC failed.Adds
tests/vaults/solana-vault-mints-error-propagation.test.tscovering account-not-found and discriminator-mismatch causes, asserting the typed-error shape and that the cause string flows through.0f92c9c: fix(vaults/fetcher): honor
parallelLimitin batch + comprehensive vault fetchersfetchVaultsBatchandfetchVaultsComprehensivepreviously accepted aparallelLimitoption but renamed it to_parallelLimitand ran every task in a batch concurrently viaPromise.all— the option was a no-op. The defaultgetVaultscall site (modules/vaults/main.ts) passesparallelLimit: 8expecting it to take effect, so RPC fan-out for a typical batch of 15 vaults was running 15-wide instead of the intended 8-wide.Both fetchers now route their per-batch work through an internal
runWithConcurrencyhelper that pulls tasks from a queue with a hard in-flight cap. The defaultparallelLimitisbatchSize, so any caller that did not specifyparallelLimitsees identical pre-fix concurrency (no regression). Callers that did specify it — including the SDK's owngetVaults— now get the cap they asked for.Adds
tests/vaults/fetcher-parallel-limit.test.tscovering: the cap, the default-preserves-prior-behavior path, and that every task still completes whenparallelLimit < batchSize.0f92c9c: perf(core/vaults): pre-compute lowercase
VAULT_SYMBOLSlookup mapgetVaultSymbol's hardcoded-fallback path usedObject.entries(VAULT_SYMBOLS).find(([k]) => k.toLowerCase() === address.toLowerCase())— an O(n) scan over the table on every cache-miss / non-canonical-case lookup. The canonical-case fast path (VAULT_SYMBOLS[address]) is preserved; the case-insensitive fallback now reads from a module-levelVAULT_SYMBOLS_LOWERCASEmap built once viaObject.fromEntries, making it O(1).The lookup precedence (backend metadata → hardcoded fallback → on-chain
getSymbol) is unchanged. The hardcoded list is@deprecatedper its existing TSDoc — backend remains canonical.Adds
tests/utils/get-vault-symbol-lowercase.test.tscovering canonical-case, lowercase, and unknown-address paths.0f92c9c: perf(core/web3): cache
getWhitelistedAssetslist per (chain, whitelist contract)V2 vault reads (
getEvmVaultV2) callgetWhitelistedAssetson the vault's whitelist contract on every invocation, and the returned list immediately fans out into per-assetgetDecimals+getSymbolreads insidebuildFormattedVault. The list itself rarely changes, so a new internal helpergetWhitelistedAssets(incore/helpers/web3.ts) wraps the contract call with anlru-cacheentry keyedwhitelisted-assets-<providerScope>-<whitelistAddress>and a 5-minute TTL. Concurrent identical reads share an in-flight promise — same pattern asgetDecimals/getSymbol.getEvmVaultV2now delegates to that helper instead of building the contract inline; the merge step that flattenscontractCalls.getWhitelistedAssetsinto the formatted vault is unchanged, so callers see the same shape.Adds
tests/utils/get-whitelisted-assets-cache.test.ts(in-flight coalescing, sequential cache-hit, no false-coalescing across addresses).
6.0.0
Integrator highlights
Breaking:
registerUserForPointsnow requires four additional parameters (chainId,signature,nonce,expiry) and no longer uses an admin API key; all existing call sites must be updated.Action: Callers must obtain an EIP-191 personal_sign signature over the canonical message template before calling
registerUserForPoints; see TSDoc for exact message format.
Full changelog
Major Changes
00c6ba9:
registerUserForPointsnow authenticates via a wallet signature instead of an admin API key. The function gains four required parameters —chainId,signature,nonce,expiry— and no longer readsoptions.augustKey. Callers must obtain a personal_sign (EIP-191) signature over a canonical message containing the lowercased user address, lowercased referrer (or"none"), chain id, nonce, and expiry; the backend reconstructs the same message and verifies the signature against the claimed wallet (EOA recovery first, then EIP-1271 for smart-contract wallets such as Safe).chainIdmust be one of the chains Upshift supports (see backendSUPPORTED_REGISTRATION_CHAINS); unsupported chains return 422. The class methodAugustVaults#registerUserForPointsand the top-levelSdk#registerUserForPointsaddchainId,signature,nonce,expiryas required positional arguments afterreferrerAddress. See the TSDoc onregisterUserForPointsfor the exact message template and a worked example.
Patch Changes
0422e61: patch an issue with version ts. This patches a broken import in v 5.1.0 and 5.1.1
5.1.1
Integrator highlights
Action: Upgrade from 5.1.0 to 5.1.1 immediately; the 5.1.0 npm tarball was built from a stale directory and is missing the Solana share-price and position fixes.
Full changelog
Patch Changes
Re-publish of 5.1.0 with a clean build. The 5.1.0 tarball on npm was shipped from a stale
lib/directory and was missing the Solana share-price + position fixes described in the 5.1.0 changelog below —lib/adapters/solana/getters.jsstill read onlydeployedAumfortotalAssets. Anyone on@augustdigital/sdk@5.1.0should bump to5.1.1.Added a
prepublishOnlyscript (pnpm clean && pnpm build) so subsequent publishes refuse to ship a stalelib/and force a fresh transpile. The 5.1.0 mishap was caused by a manualpnpm publishrun without a precedingpnpm build; the new hook makes that impossible by construction.
5.1.0
Integrator highlights
Action: Solana vault share prices and position sizes were previously mis-calculated; verify any redemption-sizing or max-action logic that relied on those values.
Action: Upgrade from any prior 5.x release to pick up the corrected Borsh IDL field order; earlier builds may have deserialized vault state fields from wrong byte offsets.
New: New
SolanaAdapter.fetchUserShareBalanceRaw({ publicKey, shareMint })returns raw share balance and decimals.New: SDK constructor now accepts a dedicated
solana: { rpcUrl, network }config entry so Solana can be configured without polluting the EVMprovidersmap.
Full changelog
Minor Changes
9dbc693: fix(solana): use
local_aum + deployed_aumfor vault total assets; add BigInt-safe share-balance helper; stop dropping Solana fromgetVaults/getVaultPositionsBump rationale (minor, not patch): this release is bug-fix-driven but adds two purely additive public-surface elements —
SolanaAdapter.fetchUserShareBalanceRaw()and the dedicatedIAugustBase.solana = { rpcUrl, network }config entry point. Per the additive-public-API rule a minor bump is required even though no existing API breaks.Root causes
getSolanaVaultread onlyvaultState.deployedAumfortotalAssets, but the on-chainVaultState::total_assets()islocal_aum + deployed_aum. The displayed share price dropped below 1.0 the instant the operator deployed any portion of the vault, even with zero PnL (jitoSOL showed0.7370against a 1:1 share supply).getVaultPositionsSolana branch passeduiAmount(a JS number) intotoNormalizedBnwith no decimals argument. It defaulted to 18 and produced awalletBalance.rawoff by10**(18 − mintDecimals), breaking redemption sizing and max-action math even though the displayednormalizedlooked plausible.The provider-availability filter (
vaultsPerAvailableProviders) had an explicit Stellar pass-through but no Solana one — Solana vaults were silently dropped from both the vault list and position list on any SDK instance whoseprovidersmap didn't register chainId-1.The IDL (
vault-idl.ts/.json) andISolanaVaultStatewere missinglocal_aum,aum_increase_limit,aum_decrease_limit, andvault_version— fields that exist in the RustVaultStatestruct (seeprograms/august-vault/src/state/vault.rs). Because the missing fields sat afterdeployed_aum, the earlier fields still deserialized correctly but every field after the drift (pda_bump,paused,padding) read from the wrong bytes.pausedhappening to read0x00is why this didn't blow up in production sooner.
Changes
adapters/solana/getters.ts: sumlocalAum + deployedAumfortotalAssets. Falls back to backend TVL when on-chain is unavailable.adapters/solana/utils.ts: newfetchUserShareBalanceRaw({ publicKey, shareMint })returning{ amount: string; decimals: number | null }from a singlegetParsedTokenAccountsByOwner.adapters/solana/index.ts: expose the helper onSolanaAdapterwith TSDoc and a worst-case RPC note.adapters/solana/types.ts: extendISolanaVaultStatewithlocalAum,aumIncreaseLimit,aumDecreaseLimit, and the (re-positioned)vaultVersion.adapters/solana/idl/vault-idl.{ts,json}: re-syncVaultStatefield order with the Rust source.main.ts: constructSolanaAdapterfrom eitherproviders[-1]or the dedicatedsolana: { rpcUrl, network }config, so partner SDK instances can opt into Solana without polluting their EVM providers map.modules/vaults/main.ts: passchain_type === 'solana'through the provider filter whenthis.solanaServiceis available — mirrors the existing Stellar clause.modules/vaults/getters.ts: Solana branch now reads via the raw helper, uses the mint's true decimals, drops theas anyonvaultState, and returnsvault: v.addressinstead of the outer parameter (mirrors the Stellar branch).modules/vaults/types.ts:ISolanaService.fetchUserShareBalanceRawis required (only impl is the in-packageSolanaAdapter, which now always provides it).
No behaviour change for EVM or Stellar paths.
Verification
Borsh layout sanity-checked against
programs/august-vault/src/state/vault.rs:36-50and against the live jitoSOL vault state at2tmMcVv2Ene7wFGebPivhwYhAZyjaJoibMz1GYVaXsB1: 455-byte account decodes cleanly with the new field order —local_aum=564_529_610,deployed_aum=1_582_093_475,aum_increase_limit=20,aum_decrease_limit=20,pda_bump=[254],vault_version=[0],paused=false, padding all-zero.local_aum + deployed_aumequals the share-mint supply at parity. Every byte accounted for.Benchmark entry added at
benchmarks/suites/sdk-methods.js:fetchUserShareBalanceRaw() [cold, no account]. Gated onBENCHMARK_SOLANA_RPC_URLso the existing EVM-only CI run isn't affected; set the env var to opt in. Uses the jitoSOL share mint with the system-program key as wallet — deterministic "no account" path that measuresgetParsedTokenAccountsByOwnerround-trip plus the short-circuit return, which is the hot path on the vault grid for users without a position.
5.0.0
Integrator highlights
Breaking: AugustSDK constructor now requires
appName(kebab-case slug, 3–64 chars); throws synchronously if missing or invalid.Breaking: fetchAugustWithKey(undefined, …) now throws
AugustAuthErrorinstead of returning a synthetic{status:500}response.Breaking: Removed
namefield fromAugustSDK; useappNameonAugustBaseinstead.Action: Add
appName: '<your-slug>'to everynew AugustSDK({…})call before upgrading.Action: Replace any
if (res.status === 500)missing-auth checks; missing key now throwsAugustAuthErrorinstead.
Full changelog
Major Changes
8881c9b: Integrator experience: require
appName, add a runtime version-nudge.Breaking — required
appName.appNameis now a required field on theAugustSDKconstructor (andIAugustBase). Pass a stable kebab-case slug identifying your application — e.g.new AugustSDK({ appName: 'acme-trader', ... }). Despite the friendly name the value is identifier-shaped: 3–64 chars,[a-zA-Z0-9._-]only (it's used as a Sentry tag and HTTP header). Use a slug like'acme-trader', not a display name like'Acme Trader'. The SDK throws synchronously from the constructor when the value is missing, empty, or out of the allowed shape.Why: the SDK now tags outbound analytics events with
app.name, so the August Digital team can attribute error spikes to the right consuming application and reach out about breaking changes / critical bugs. See the "App Name" section inpackages/sdk/README.md.Migration: add
appName: '<your-slug>'to your existingnew AugustSDK({ ... })call. No other changes required.Additive — version-nudge on construction. On non-production builds the SDK now performs one best-effort npm-registry check per session and prints a
console.warnbanner when a newer@augustdigital/sdkis available. The check never runs inNODE_ENV=production, can be silenced withAUGUST_SDK_DISABLE_VERSION_CHECK=1, or programmatically withnew AugustSDK({ versionCheck: { enabled: false }, ... }). Never blocks construction; failures are silent. New exports:runVersionCheck,IVersionCheckConfig,compareSemver.
Minor Changes
c24003b: feat: production-grade hardening
Security & errors
New typed error hierarchy:
AugustSDKError,AugustAuthError,AugustNetworkError,AugustTimeoutError,AugustValidationError,AugustRateLimitError,AugustServerError, plusisAugustSDKErrortype guard. All extendErrorso existinginstanceof Errorconsumers are unaffected.Secret sanitization in error messages, logger, and Slack adapter via
sanitizeString/sanitizeError/sanitizeForLogging.URL injection hardening:
buildAugustUrlrejects unknown server keys, absolute URLs, and protocol-relative paths; origin check enforces same-origin.fetchAugustWithKey(undefined, …)now throwsAugustAuthError(AUTH_MISSING_KEY)instead of returning a synthetic{status: 500}response — callers usingif (res.status === 200)previously misclassified missing-auth as a 500 server error; they now receive a proper typed error.verifyAugustKeyshort-circuits empty keys soinit()behavior is unchanged.overrideflag onIFetchAugustOptionsis@deprecatedwith a one-time runtime warning; will be removed in the next major.HTTP errors are now typed by status: 401 →
AugustAuthError, 429 →AugustRateLimitError, elseAugustServerError.Response.headers.get('x-correlation-id')(was bracket-accessed; alwaysundefined).
Transport
Per-request
signal: AbortSignalandtimeoutMs: numberonIFetchAugustOptions. Combined with the default timeout viaAbortSignal.any(Node 22+) with a manual relay + cleanup fallback. Distinguishes caller-cancel from timeout via an internaltimedOutflag.
Observability
New
ILoggerinterface andLogger.setStructuredLogger()alongside the existing Sentry-compatibleSDKLogger. Pino-friendly: pass a context object as the first arg.
Performance
Parallelized
getVaultloans + allocations (Promise.allSettled, preserves original control flow).Removed redundant
fetchTokenizedVaultcalls ingetVaultLoans/getVaultSubaccountLoans.createProvider(rpcUrl, chainId?)enables ethers'staticNetwork(skips theeth_chainIdround-trip).getInfuraProviderroutes throughcreateProvider(was rebuilding per call).decimals/symbol/receipt-tokencaches are chain-scoped viaproviderScope.
Bundle
Buffer polyfill extracted to
polyfills.ts; guarded against clobbering a consumer-setBuffer.sideEffects: ["./lib/polyfills.js"]lets bundlers tree-shake the rest of the SDK.Source maps excluded from the npm tarball.
Bug fixes
fetchAugustWithBearerno longer crashes whenoptionsis undefined (options?.everywhere).AbortSignalfallback path now removes itsabortlistener on completion (no more leak across long-lived caller signals).Slack adapter's webhook fetch has a 5s timeout.
sanitizeErrorpreserves typed-error subclasses by cloning via prototype + own properties instead of calling the constructor (which would have misaligned positional args likeAugustAuthError(code, message, opts)).AugustSDKErrorand subclasses ship atoJSON()soJSON.stringify(err)no longer returns"{}".code,correlationId,status,timeoutMs,retryAfterMs, andcauseare all included.
No public API breaks. All additions are opt-in. The only behavior change is
fetchAugustWithKey(undefined, …)throwing instead of returning a fake 500 — the thrown value is still anErrorinstance.8881c9b: feat(sdk): expose
getVaultRedemptionHistoryon theAugustVaultsmodule and the top-levelAugustSDKclass. Wraps the existing module-level getter with the standard option-plumbing (RPC resolution fromchainId,augustKey/subgraphKey/headersfrom the SDK instance), validates the vault input, and returns the same historical redemption records the underlying getter produces. Stellar vaults continue to return[]until on-chain indexing lands for that adapter.
Patch Changes
7027223: fix: vault read paths no longer hang or surface ethers'
network is not available yetwhen the configured RPC is unreachable or rate-limitedThree related changes that together resolve
august vault tvl <addr> --chain <id>failures (crypticNETWORK_ERRORon a healthy RPC, infinite "JsonRpcProvider failed to detect network" retry loop on a 403/401 RPC):providerScope(cache-key builder used bygetDecimals,getReceiptTokenAddress, …) now tolerates ethers v6's lazy-network state. Readingprovider._networkis a getter that throwsnetwork is not available yetuntil the first successful request resolves the chain id; the throw was bubbling out of every cached vault read on freshly constructed providers.AugustVaults.getVaultTvlnow threadschainIdinto the getter options, and the EVM branch ofgetVaultTvl(packages/sdk/src.ts/modules/vaults/getters.ts) forwards it tocreateProvider. This sets ethers'staticNetwork, skipping theeth_chainIdround-trip and, more importantly, preventing the indefinite network-detection retry loop when the RPC returns 4xx errors.createProvidernow throws a clear, remediable error when called with a missing or emptyrpcUrl, instead of silently constructing aJsonRpcProviderpointed athttp://localhost:8545.
f0741e2: fix: HyperEVM RPC compatibility for
getWithdrawalRequestsWithStatusc14c10b: chore: remove unused
namefield fromAugustSDK. The field was declared but never assigned and never read —appName(onAugustBase) is the single source of truth for the app identifier.0cb921a: fix: cap
fetchTokenizedVaultscache at 10 minutes and avoid stale-get evictionfetchTokenizedVaults(bulk list) was callingCACHE.set(key, value)with no TTL override, falling back to the 24-hour global default — so vault config changes made on the backend (fee rates, fee waivers, etc.) could take up to 24h to surface to bulk-list consumers. The cache lookup also calledCACHE.get(key)twice in a row; because the globalCACHEis configured withallowStale: true, the first.get()on a stale entry returns it and evicts it, leaving the second.get()undefined. Switched togetSafeCache(which uses.has()and so never triggers stale-get eviction) and set an explicit 10-minute TTL to matchfetchTokenizedVault(single).
4.27.0
Integrator highlights
Breaking: getWithdrawalRequestsWithStatus now requires a chainId argument; calls without it will break cross-chain queries.
Action: Pass
chainIdto all existinggetWithdrawalRequestsWithStatuscalls.New:
AugustVaults.rwaRedeemAsset()andpreviewRwaRedemption()added for RWA instant redemption flows.New: New
instant_redeem_configfield onIVaultreturned fromgetVault/getVaults.
Full changelog
Minor Changes
78231b6: feat: add RWA instant redemption — new
AugustVaults.rwaRedeemAsset()andpreviewRwaRedemption()methods, plus aninstant_redeem_configfield onIVaultreturned fromgetVault/getVaults. The SDK automatically routes redemption calls to the correctRwaRedeemSubaccountfor each vault.
Patch Changes
5766173: fix:
getWithdrawalRequestsWithStatusnow requires achainIdargument so cross-chain queries return correct results.8872391: feat: add helpers for OFT (LayerZero Omnichain Fungible Token) flows.
4.25.0
Integrator highlights
Action: New
show_cap_filledfield on tokenized vault responses can now drive cap-filled UI states.New:
getWithdrawalRequestsWithStatusadded for tracking withdrawal request statuses.New: New
getVaultPendingRedemptionsmethod added onAugustVaults.New: New
fetchTokenizedVaultSubaccountLoansfunction available for subaccount loan data on tokenized vaults.
Full changelog
Minor Changes
a267145: feat: add a Stellar SDK adapter — Soroban RPC support, transaction building and submission, and end-to-end localnet test coverage.
455b625: feat: add
getWithdrawalRequestsWithStatusfor tracking the status of withdrawal requests.ad5ea73: chore: remove SUI points from vault responses.
7e5aa22: feat: add Stellar vault support (backend-only) including a Stellar adapter, routing, and a shared vault builder.
Patch Changes
8f1bcee: chore: refactor Solana vault adapter getters into a shared
buildBackendVaultutility (no public API change).c721801: fix: include PnL data in LayerZero (LZ) vault responses.
e12e957: fix: prevent silent data loss in
getWithdrawalRequestsWithStatuswhen responses span multiple pages.d6e7f96: feat: add
fetchTokenizedVaultSubaccountLoansfor retrieving subaccount loan data on tokenized vaults.bba0483: feat: add
show_cap_filledto the tokenized vault response so callers can render cap-filled UI states.fd90233: feat: add a
getVaultPendingRedemptionsmethod onAugustVaults.
4.24.6
Integrator highlights
Action: CommonJS builds previously had
AugustBaseundefined due to circular imports; upgrade to fix.Action: Solana multi-vault programs now correctly read the share mint from on-chain state instead of PDA derivation.
New: earnAUSD support added over LayerZero.
Full changelog
Patch Changes
bf55850: feat: add earnAUSD support over LayerZero.
301e84e: fix: resolve a circular dependency in the Solana adapter imports that caused
AugustBaseto be undefined in CommonJS builds.e0a1135: fix: forward
vaultAddresstogetVaultStatefromgetVaultPositionsso PDA derivation no longer returns the wrong address.40d8d3f: fix: read the share mint from on-chain vault state (instead of PDA derivation) so multi-vault Solana programs are supported correctly.
ebefff4: fix: ensure the tokenized vault API call always issues its query.
4.14.0
Integrator highlights
Action: Migrate
IVaultAnnualizedApy.hgETH30dLiquidAPYtoliquidAPY30Daybefore 2026-01-01.Action: Migrate
IVaultAnnualizedApy.hgETH7dLiquidAPYtoliquidAPY7Daybefore 2026-01-01.New:
getVaultAnnualizedApy,getVaultSummary, andgetVaultWithdrawalsmethods are now available.New: New types
IVaultAnnualizedApy,IVaultSummary, andIVaultWithdrawalsare exported.
Full changelog
Minor Changes
0364b53: feat: add new vault API methods.
New Methods:
getVaultAnnualizedApy— fetch annualized APY metrics for vaults (cUSDO, tETH, wstETH, rsETH).getVaultSummary— fetch a summary of a vault (name, type, chain, recent returns).getVaultWithdrawals— fetch a withdrawal summary and the pending withdrawal queue.
New Types:
IVaultAnnualizedApyIVaultSummaryIVaultWithdrawals
Deprecation Notice:
IVaultAnnualizedApy.hgETH30dLiquidAPY— useliquidAPY30Dayinstead (removal: 2026-01-01).IVaultAnnualizedApy.hgETH7dLiquidAPY— useliquidAPY7Dayinstead (removal: 2026-01-01).
Documentation:
Vault method documentation added to
docs/02-vaults.md.
4.13.0
Integrator highlights
Action: Migrate from deprecated
historical_snapshotson vault response togetVaultHistoricalTimeseries.New: Katana chain is now supported.
New: Subgraph configuration added for superMON, earnMON, and k3EUROP vaults.
Full changelog
Minor Changes
01f6203: feat: add support for the Katana chain.
Patch Changes
e58170f: fix: improve observability when Goldsky subgraph requests fail.
d417f0b: feat: add subgraph configuration for the superMON, earnMON, and k3EUROP vaults.
fe74f64: fix: update the query parameters used by the tokenized vault endpoints; deprecate
historical_snapshotson the vault response — usegetVaultHistoricalTimeseriesinstead.
4.6.1
Integrator highlights
Action: Deposit cap is no longer fetched on initial vault load; ensure your integration handles on-demand loading.
New: Tokenized vault response now includes a
historical_apyfield.New: New deposit-with-permit function allows depositing using EIP-2612 signatures.
Full changelog
Patch Changes
79c3917: feat: add
historical_apyto the tokenized vault response.b01879f: feat: add a deposit-with-permit function so callers can deposit using EIP-2612 signatures.
5506682: perf: reduce RPC calls during vault fetching.
c7b052e: perf: remove the deposit cap query from the initial vault fetch — it's loaded on demand instead.
3.15.1
Integrator highlights
New: Debank response now includes an error field for failed responses.
Full changelog
Patch Changes
1ef7bfb: adding coingecko key to staking
04c7782: add error response to debank res
Updated dependencies [1ef7bfb]
Updated dependencies [04c7782]
@augustdigital/services@3.15.1
@augustdigital/vaults@3.15.1
@augustdigital/pools@3.15.1
@augustdigital/types@3.15.1
@augustdigital/utils@3.15.1
@augustdigital/abis@3.15.1
3.3.0
Integrator highlights
New: Event objects now include a hash field for easier transaction lookup.
New: User history fetching behavior has been updated.
Full changelog
Minor Changes
a86b316: update
c5c2570: update hash in events
c9b3c1a: update
705637a: update fetch user history
b6e3aba: update version
Patch Changes
Updated dependencies [a86b316]
Updated dependencies [c5c2570]
Updated dependencies [c9b3c1a]
Updated dependencies [705637a]
Updated dependencies [b6e3aba]
@augustdigital/pools@3.3.0
@augustdigital/types@3.3.0
@augustdigital/utils@3.3.0
@augustdigital/abis@3.3.0
@augustdigital/vaults@3.3.0
3.1.0
Integrator highlights
New: Pools now expose an
isFeeWaivedboolean field.New: User history data has been updated with new information.
Full changelog
Minor Changes
81ab166: add isFeeWaived to pools
25bc103: update user history
2c4618a: remove console
Patch Changes
Updated dependencies [81ab166]
Updated dependencies [25bc103]
Updated dependencies [2c4618a]
@augustdigital/pools@3.1.0
@augustdigital/types@3.1.0
@augustdigital/utils@3.1.0
@augustdigital/abis@3.1.0
@augustdigital/sdk@3.1.0
0.0.3
Integrator highlights — internal changes only; no integrator action needed.
Full changelog
Patch Changes
d72f854: (v0.0.3) testing github workflows
2f95c56: v0.0.3 edited readme and testing automated npm publish github workflow
c388be5: (v0.0.2) changeset working appropriately
Updated dependencies [d72f854]
Updated dependencies [2f95c56]
Updated dependencies [c388be5]
@augustdigital/pools@0.0.3
@augustdigital/types@0.0.3
@augustdigital/utils@0.0.3
@augustdigital/abis@0.0.3
Last updated