@circle-fin/app-kit 1.6.1 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/CHANGELOG.md +225 -0
  2. package/README.md +28 -5
  3. package/bridge.cjs +19951 -0
  4. package/bridge.cjs.map +1 -0
  5. package/bridge.d.cts +6603 -0
  6. package/bridge.d.mts +6603 -0
  7. package/bridge.d.ts +6603 -0
  8. package/bridge.mjs +19944 -0
  9. package/bridge.mjs.map +1 -0
  10. package/chains.cjs +1018 -1087
  11. package/chains.d.cts +2060 -0
  12. package/chains.d.mts +2060 -0
  13. package/chains.d.ts +40 -37
  14. package/chains.mjs +1018 -1087
  15. package/context.cjs +59 -0
  16. package/context.cjs.map +1 -0
  17. package/context.d.cts +6428 -0
  18. package/context.d.mts +6428 -0
  19. package/context.d.ts +6428 -0
  20. package/context.mjs +57 -0
  21. package/context.mjs.map +1 -0
  22. package/earn.cjs +7940 -4626
  23. package/earn.d.cts +8340 -0
  24. package/earn.d.mts +8340 -0
  25. package/earn.d.ts +987 -85
  26. package/earn.mjs +7937 -4627
  27. package/estimateBridge.cjs +19889 -0
  28. package/estimateBridge.cjs.map +1 -0
  29. package/estimateBridge.d.cts +6483 -0
  30. package/estimateBridge.d.mts +6483 -0
  31. package/estimateBridge.d.ts +6483 -0
  32. package/estimateBridge.mjs +19882 -0
  33. package/estimateBridge.mjs.map +1 -0
  34. package/estimateSwap.cjs +21577 -0
  35. package/estimateSwap.cjs.map +1 -0
  36. package/estimateSwap.d.cts +6625 -0
  37. package/estimateSwap.d.mts +6625 -0
  38. package/estimateSwap.d.ts +6625 -0
  39. package/estimateSwap.mjs +21571 -0
  40. package/estimateSwap.mjs.map +1 -0
  41. package/index.cjs +15844 -11589
  42. package/index.d.cts +26657 -0
  43. package/index.d.mts +26657 -0
  44. package/index.d.ts +5667 -688
  45. package/index.mjs +15834 -11590
  46. package/package.json +66 -32
  47. package/swap.cjs +21577 -0
  48. package/swap.cjs.map +1 -0
  49. package/swap.d.cts +6721 -0
  50. package/swap.d.mts +6721 -0
  51. package/swap.d.ts +6721 -0
  52. package/swap.mjs +21571 -0
  53. package/swap.mjs.map +1 -0
  54. package/unifiedBalance.cjs +20557 -0
  55. package/unifiedBalance.cjs.map +1 -0
  56. package/unifiedBalance.d.cts +7276 -0
  57. package/unifiedBalance.d.mts +7276 -0
  58. package/unifiedBalance.d.ts +7276 -0
  59. package/unifiedBalance.mjs +20551 -0
  60. package/unifiedBalance.mjs.map +1 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,230 @@
1
1
  # @circle-fin/app-kit
2
2
 
3
+ ## 1.8.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Vault results from `getVaults`, `exploreVaults`, and `exploreVaultsIterator`
8
+ now include a `circleGuarded` boolean that marks vaults on Circle's curated
9
+ Circle-guarded list.
10
+
11
+ ```typescript
12
+ const result = await kit.getVaults({
13
+ vaults: [{ chain: "Ethereum", vaultAddress: "0xbeef..." }],
14
+ });
15
+ console.log(result.vaults[0].circleGuarded);
16
+ ```
17
+
18
+ This release requires an Earn Service version that returns the
19
+ `circleGuarded` field.
20
+
21
+ - EarnKit can now discover vaults with the new `exploreVaultsIterator` and
22
+ `exploreVaults` operations.
23
+
24
+ `exploreVaultsIterator` lazily iterates every vault available on a chain,
25
+ fetching pages on demand so there is no page arithmetic to manage:
26
+
27
+ ```typescript
28
+ for await (const vault of kit.exploreVaultsIterator({
29
+ chain: "Arc_Testnet",
30
+ sortBy: "apy",
31
+ })) {
32
+ console.log(`${vault.name}: ${(vault.currentApy * 100).toFixed(2)}% APY`);
33
+ }
34
+ ```
35
+
36
+ `exploreVaults` fetches a single page with pagination metadata for paged
37
+ UIs. Both operations accept optional `protocol`, `asset`, `minApy`, and
38
+ `minTvl` filters (protocol and asset are matched case-insensitively) and a
39
+ `sortBy` of `apy`, `tvl`, or `name`.
40
+
41
+ Also available through `@circle-fin/app-kit` as `kit.earn.exploreVaults()` /
42
+ `kit.earn.exploreVaultsIterator()` and the functional `earnExploreVaults` /
43
+ `earnExploreVaultsIterator` exports.
44
+
45
+ No changes are required for custom `EarningProvider` implementations: the
46
+ new `exploreVaults` method is optional on the interface. Providers that do
47
+ not implement it cause a clear "no provider supports exploreVaults" error
48
+ when vault discovery is called; implement the method to opt in.
49
+
50
+ - Earn quotes now include gas fee estimates.
51
+
52
+ `getDepositQuote`, `getWithdrawalQuote`, and `getClaimRewardsQuote` now return a
53
+ `gasFees` array estimating the native-token gas cost of each transaction in the
54
+ flow (approval, deposit, withdraw, claim), so you can show users the expected
55
+ cost before they commit. When an estimate cannot be produced, the entry's `fees`
56
+ is `null` and `error` carries a short message describing why, while the rest of
57
+ the quote still resolves.
58
+
59
+ Also available through `@circle-fin/app-kit`'s earn quote operations.
60
+
61
+ - Enable Circle's Forwarding Service as a destination for Solana (mainnet and devnet). A Gateway `spend` with `useForwarder: true` to a Solana destination is now accepted instead of being rejected.
62
+ - Add cross-chain swap support to SwapKit, AppKit, and the Stablecoin Service swap provider.
63
+ - `swap` and `estimate` can now route the output token to another supported chain with `to.chain`.
64
+ - Cross-chain swaps can send the output to a recipient on the destination chain with `to.recipientAddress`.
65
+ - `getSwapStatus` and `waitForSwap` can now track cross-chain swaps until they finish, including progress details for source and destination activity.
66
+ - Swap estimates and results include `chainIn`, `chainOut`, and `progress` so apps can show where a swap started, where it will settle, and its current state.
67
+ - Invalid transaction hashes or unsupported chain values are reported as structured validation errors before a status request is sent.
68
+
69
+ - Add `getTokenRates` to SwapKit and AppKit for fetching USD rates for tokens on a chain.
70
+ - Look up rates by registered token symbol, native token alias (`NATIVE`, `ETH`, `POL`, etc.), raw EVM token address, or Solana mint.
71
+ - Token symbols are resolved through the kit token registry for the requested chain.
72
+ - Native tokens are normalized to the service native-token address before the request is sent.
73
+ - Invalid token or chain values return structured validation errors instead of silently returning an empty rate map or surfacing a raw service error.
74
+ - Each returned rate carries `priceUSD` and `fetchedAt`, plus an optional `decimals` (the token's on-chain precision) when the service reports it.
75
+
76
+ - Surface a typed, retryable `EarnError.PAUSED` when EarnKit is temporarily
77
+ paused off-chain (the earn service returns backend code `380414` /
78
+ `EARNKIT_OFFCHAIN_PAUSED` / HTTP `409`).
79
+
80
+ | Code | Name | Type | Recoverability |
81
+ | ------ | ------------- | --------- | -------------- |
82
+ | `8104` | `EARN_PAUSED` | `SERVICE` | `RETRYABLE` |
83
+ - `@circle-fin/earn-kit` / `@circle-fin/app-kit`: the publicly re-exported
84
+ `EarnError` registry now includes `EARN_PAUSED`. Consumers that branch on
85
+ `EarnError` (or on `recoverability`) gain this value and can detect the
86
+ pause and retry later.
87
+ - `@circle-fin/provider-earn-service`: `parseEarnApiError` now maps `380414`
88
+ to `EarnError.PAUSED`, so `EarnServiceProvider` deposit/withdraw/claim calls
89
+ throw a retryable `EARN_PAUSED` instead of falling through to the previous
90
+ fatal `VALIDATION_FAILED`.
91
+
92
+ - The publicly re-exported `InputError` registry now includes three new
93
+ chain pre-flight codes that the `/next` EVM adapters can throw:
94
+
95
+ | Code | Name |
96
+ | ------ | ----------------------------- |
97
+ | `1010` | `INPUT_CHAIN_MISMATCH` |
98
+ | `1011` | `INPUT_CHAIN_SWITCH_REJECTED` |
99
+ | `1012` | `INPUT_UNRECOGNIZED_CHAIN` |
100
+
101
+ Consumers that branch on `InputError` (or on raw numeric codes) gain
102
+ these values: `CHAIN_MISMATCH` when the connected wallet is on a
103
+ different chain than the request targets, `CHAIN_SWITCH_REJECTED` when
104
+ the user declines a programmatic switch, and `UNRECOGNIZED_CHAIN` when a
105
+ chain definition cannot be resolved.
106
+
107
+ - **Behavioral change:** the re-exported `isRetryableError` no longer
108
+ treats nonce errors (`4003` / `RPC_NONCE_ERROR`) as retryable.
109
+
110
+ A nonce error is genuinely ambiguous — the transaction may already have
111
+ been accepted (the nonce moved on), a concurrent transaction from the
112
+ same key may have consumed the slot, or a local nonce tracker may have
113
+ drifted. Generic automatic retry risks a double-spend or a
114
+ nonce-conflict flip-flop, so `4003` was removed from
115
+ `DEFAULT_RETRYABLE_ERROR_CODES` and callers must now decide explicitly
116
+ whether to refresh the nonce and resubmit.
117
+
118
+ For `@circle-fin/app-kit` specifically, the documented resume guard
119
+ `if (isRetryableError(failedStep.error)) await kit.retryBridge(...)` now
120
+ skips bridges that failed on a nonce error; handle code `4003` yourself
121
+ if you want to refresh the nonce and retry.
122
+
123
+ - Add APIs to track a cross-chain Earn deposit after it is submitted.
124
+
125
+ A cross-chain `deposit()` returns an `execId` while the bridge (source burn ->
126
+ CCTP attestation -> destination mint) is still settling. Two new kit methods let
127
+ you follow it:
128
+ - `kit.getCrossChainDepositStatus({ execId })` - read the deposit's current
129
+ bridge status (source, CCTP, and destination hops) once.
130
+ - `kit.waitForCrossChainDeposit({ execId, pollIntervalMs?, maxWaitMs?, signal? })`
131
+ - poll until the deposit settles, fails, or the wait budget elapses (default
132
+ 20 min). On timeout it resolves with the last status instead of throwing, so
133
+ you can see where the bridge stalled. Pass an `AbortSignal` to cancel a long
134
+ wait. While polling it emits events you can subscribe to with
135
+ `kit.on('crossChainDepositStatus', ...)`.
136
+
137
+ New exported types: `EarnCrossChainDepositStatus`,
138
+ `EarnCrossChainDepositWaitResult`, `EarnBridgeHopStatus`,
139
+ `EarnBridgeCctpStatus`, plus the param types and schemas for both methods. All
140
+ are re-exported from `@circle-fin/app-kit` with earn-prefixed names.
141
+
142
+ - Surface the source-collected bridge fees in cross-chain Earn deposit quotes, and let callers pick the CCTP transfer speed.
143
+
144
+ New:
145
+ - `getDepositQuote` now accepts a cross-chain variant: pass a destination `chain` and `address` that differ from `from.chain` (same `SameChain` / `CrossChain` discriminator pattern as `deposit()`). Same-chain quotes are unchanged.
146
+ - Cross-chain quotes return the source-collected bridge fees in `EarnDepositQuoteInfo.fees` as one entry per fee item. Each entry carries its own `type` (e.g. `'FORWARD'`, `'PRE_FINALITY'`) and `status` (e.g. `'estimated'` for a pre-sign estimate). Same-chain quotes return `fees: []`.
147
+ - Cross-chain `deposit()` and `getDepositQuote()` accept an optional `transferSpeed` (`'FAST'` | `'SLOW'`), forwarded to the bridge prepare request so the quote prices — and the deposit burns — the chosen CCTP finality path.
148
+ - New param types: `SameChainGetDepositQuoteParams` / `CrossChainGetDepositQuoteParams` (the existing `GetDepositQuoteParams` becomes their union). Provider gains `SameChainGetDepositQuoteServiceParams` / `CrossChainGetDepositQuoteServiceParams`.
149
+ - The provider sends `sourceChain` / `sourceAddress` / `transferSpeed` to `POST /v1/earnKit/deposit/quote` and parses the per-fee `fees[]` response (each with `type` + `status`).
150
+ - `AssetAmount` gains optional `type` and `status` tags (used on fee entries).
151
+ - The cross-chain pre-sign value guard is now fee-aware: the prepared bundle's `feeQuote` (`feeToken` + `items[]`) is parsed, the fee token is pinned to the source token contract, and the signed authorization `value` is checked against `principal + sum(feeQuote.items[].amount)` rather than the principal alone, so fee-bearing deposits are accepted while any other value tampering is still rejected before signing.
152
+
153
+ Notes:
154
+ - The cross-chain fees are pre-sign **estimates** sourced from the bridge prepare path; the value shown at quote time may differ from the amount locked at deposit/sign. This is signalled per fee via `status: 'estimated'`.
155
+ - Existing same-chain `getDepositQuote` callers are unaffected — the response shape is unchanged for same-chain quotes.
156
+
157
+ - Add cross-chain Earn deposits through the bridge prepare, sign, and submit flow.
158
+
159
+ Cross-chain deposits use the same nested `from`/`to` input shape as the other kits: `from: { adapter, chain }` is the source signer and `to: { chain, recipientAddress }` is the Earn destination. `from.chain` and `to.chain` are constrained at compile time to the supported route (Ethereum Sepolia, Arbitrum Sepolia, or Base Sepolia as sources; Arc Testnet as the destination), the source adapter must support `signTypedData`, and amounts accept at most 6 decimal places (USDC precision). Cross-chain results report the bridge `execId`, an API-defined bridge lifecycle `status`, `sourceChain`/`destinationChain`, and the prepared bundle expiry.
160
+
161
+ Every published name keeps its existing shape; cross-chain support lands under new names:
162
+ - `EarnDepositOutcome` is the new union of `EarnSameChainDepositResult | EarnCrossChainDepositResult`. Narrow with `result.kind === 'cross-chain'` — `kind` is always set at runtime, but optional on the same-chain member so the pre-cross-chain result shape remains assignable.
163
+ - `AnyDepositParams` (kit) and `AnyDepositServiceParams` (provider) are the new param unions of the same-chain and cross-chain variants; `anyDepositParamsSchema` is the matching validation schema.
164
+ - `deposit()` gains overloads: same-chain params resolve to `EarnSameChainDepositResult`, cross-chain params to `EarnCrossChainDepositResult`, so existing same-chain call sites keep their narrow result type.
165
+ - Bridge phases emit on a new `crossChainDeposit` event (`method: 'prepare' | 'sign' | 'submit'`, `values: EarnBridgeDepositStep`). The existing `deposit` event is unchanged and never fires bridge phases.
166
+ - `EarningProvider` gains an **optional** `supportsCrossChainDeposit(source, destination)` method (mirroring swap-kit's route-aware `supportsRoute`). The kit only routes cross-chain deposits to providers that implement it and return `true`; existing provider implementations keep compiling and never receive cross-chain params.
167
+
168
+ Deprecations (existing aliases keep working):
169
+ - `EarnDepositResult` — use `EarnSameChainDepositResult`, or `EarnDepositOutcome` for cross-chain-aware code. This alias may repoint to `EarnDepositOutcome` in the next major.
170
+ - `DepositParams` / `DepositServiceParams` — use `SameChainDepositParams` / `SameChainDepositServiceParams`, or the `Any*` unions for cross-chain-aware code.
171
+ - `depositParamsSchema` — use `anyDepositParamsSchema`, which also accepts cross-chain deposit params.
172
+
173
+ Type changes (diagnostic types only):
174
+ - `EarnErrorTrace`: the deposit variant's `params` is now `AnyDepositServiceParams`, and `steps` may include `EarnBridgeDepositStep` entries for cross-chain deposits.
175
+ - `EarningProvider.retry()` and `EarnKit.retry()` may now resolve to `EarnCrossChainDepositResult` when resuming a cross-chain deposit.
176
+ - `EarnActionName` gains `'crossChainDeposit'`.
177
+
178
+ ### Patch Changes
179
+
180
+ - Canonicalize native-stablecoin token spellings across the swap path. On chains whose native gas token is USDC (e.g. Arc), the `NATIVE` symbol, the EIP-7528 sentinel (`0xEeee…`), and the zero address now all resolve to the USDC contract address. As a result, `NATIVE` and `USDC` are treated as the same asset (so `supportsRoute('NATIVE', 'USDC', Arc)` returns `false`), `getTokenDecimals` resolves native-alias addresses to the chain's native decimals without an on-chain call, and the service never receives a native spelling for what is already canonical as USDC. This is derived generically from chain metadata, so any future native-stablecoin chain is covered automatically. Behavior on all other chains is unchanged.
181
+
182
+ `@circle-fin/app-kit`'s `send` now canonicalizes EVM native-alias address spellings (EIP-7528 sentinel `0xEeee…`, zero address) to `'NATIVE'` before routing. Without this, those addresses passed validation as custom token addresses and reached `token.transfer` (the ERC-20 rail) while `getTokenDecimals` returned 18-decimal native amounts — a decimals↔rail mismatch that reverts on Arc. After canonicalization both the rail (`native.transfer`) and the decimals (18) are consistent on EVM chains. On non-EVM chains, those EVM placeholder addresses are left to chain-specific token validation and rejected instead of being promoted to native transfers.
183
+
184
+ - EarnKit now validates amount precision and format locally to match the Earn
185
+ Service, so malformed amounts fail fast with a clear SDK error instead of a
186
+ server round-trip.
187
+ - Same-chain deposit/withdraw/quote amounts are now capped at 6 decimal places
188
+ (USDC/EURC), matching the server and the existing cross-chain amount schema.
189
+ Previously up to 18 decimal places passed local validation and only the
190
+ server rejected 7+ decimal-place inputs.
191
+ - Non-canonical numeric forms are now rejected locally on both same-chain and
192
+ cross-chain amounts: a leading decimal point ('.5') and leading zeros
193
+ ('00.5', '07'). These passed the generic decimal-string validator but were
194
+ rejected by the server.
195
+
196
+ Well-formed amounts are unaffected.
197
+
198
+ - Fix forwarded-route support to depend only on the destination chain.
199
+
200
+ `supportsRoute(source, destination, 'USDC', true)` previously also required the
201
+ source chain's `cctp.forwarderSupported.source` to be `true`. Today's Forwarding
202
+ Service operates on the destination chain, so any CCTP v2 chain can originate a
203
+ forwarded transfer; the route check now gates only on the destination chain's
204
+ `cctp.forwarderSupported.destination`, matching the bridge execution path.
205
+
206
+ `cctp.forwarderSupported.source` is now `false` for every chain definition,
207
+ reflecting that source-side forwarding is not yet available. This corrects
208
+ metadata that previously implied source-side forwarding was supported.
209
+
210
+ Also surfaced through `@circle-fin/bridge-kit` and `@circle-fin/app-kit`.
211
+
212
+ - Fix broken `exports` maps so subpath and CommonJS entry points resolve correctly.
213
+
214
+ `@circle-fin/app-kit`: the `./context`, `./bridge`, `./estimateBridge`, `./swap`, `./estimateSwap`, and `./unifiedBalance` subpath exports pointed at `./kit/...` source-style paths that the build never emits — it flattens additional entry points to the package root. `./context`, `./bridge`, and `./estimateBridge` now point at the built `./context.*`, `./bridge.*`, and `./estimateBridge.*` files. `./swap`, `./estimateSwap`, and `./unifiedBalance` — documented in the changelog and JSDoc but never wired into the build — are now emitted as package-root entry points and added to `files`, so all six documented subpaths resolve under Node and bundlers.
215
+
216
+ `@circle-fin/provider-stablecoin-service`: `main` and `exports["."].default` referenced `./index.cjs.js`, a file the build never produces; both now point at the real `./index.cjs`.
217
+
218
+ ## 1.7.0
219
+
220
+ ### Minor Changes
221
+
222
+ - EarnKit (exposed under `kit.earn`) now emits step-level events for multi-phase operations (`deposit`, `withdraw`, `claimRewards`) via `kit.earn.on()` / `kit.earn.off()`, and exposes `kit.earn.retry(error)` to resume an operation that failed after a prior phase (such as a token approval) already succeeded. Failed earn operations now throw a `KitError` carrying step progress and resume context, and `isRetryableError` recognizes `RESUMABLE` errors as retryable.
223
+
224
+ ### Patch Changes
225
+
226
+ - `kit.bridge` and `kit.unifiedBalance` operations (`deposit`, `depositFor`, `addDelegate`, `removeDelegate`, `initiateRemoveFund`, `removeFund`) no longer reject Gas Station-enabled smart-contract accounts (SCAs) with zero native balance. EOA wallets without native funds will still fail at simulation with the underlying RPC error.
227
+
3
228
  ## 1.6.1
4
229
 
5
230
  ### Patch Changes
package/README.md CHANGED
@@ -143,9 +143,9 @@ npm install @circle-fin/adapter-ethers-v6 ethers
143
143
  yarn add @circle-fin/adapter-ethers-v6 ethers
144
144
 
145
145
  # For Solana
146
- npm install @circle-fin/adapter-solana @solana/web3.js @solana/spl-token
146
+ npm install @circle-fin/adapter-solana @solana/web3.js
147
147
  # or
148
- yarn add @circle-fin/adapter-solana @solana/web3.js @solana/spl-token
148
+ yarn add @circle-fin/adapter-solana @solana/web3.js
149
149
  ```
150
150
 
151
151
  ### Chain Definitions
@@ -345,7 +345,7 @@ For the full Unified Balance API, see the [`@circle-fin/unified-balance-kit` REA
345
345
  Deposit into and withdraw from DeFi lending vaults, claim rewards, and query positions:
346
346
 
347
347
  ```typescript
348
- import { AppKit, EarnChain } from '@circle-fin/app-kit'
348
+ import { AppKit, Blockchain, EarnChain } from '@circle-fin/app-kit'
349
349
  import { createViemAdapterFromPrivateKey } from '@circle-fin/adapter-viem-v2'
350
350
 
351
351
  const kit = new AppKit()
@@ -360,13 +360,32 @@ const quote = await kit.earn.getDepositQuote({
360
360
  amount: '100.50',
361
361
  })
362
362
 
363
- // Execute the deposit
364
- await kit.earn.deposit({
363
+ // Execute a same-chain deposit
364
+ const depositResult = await kit.earn.deposit({
365
365
  from: { adapter, chain: EarnChain.Arc_Testnet },
366
366
  vaultAddress: '0xAabbeF1D3971c710276ed41eC791BbE14CdB8E88',
367
367
  amount: '100.50',
368
368
  })
369
369
 
370
+ console.log(`Deposit submitted: ${depositResult.txHash}`)
371
+
372
+ // Execute a cross-chain deposit into an Earn vault
373
+ const bridgeDeposit = await kit.earn.deposit({
374
+ from: { adapter, chain: Blockchain.Ethereum_Sepolia },
375
+ to: {
376
+ chain: EarnChain.Arc_Testnet,
377
+ recipientAddress: '0x1234567890123456789012345678901234567890',
378
+ },
379
+ vaultAddress: '0xAabbeF1D3971c710276ed41eC791BbE14CdB8E88',
380
+ amount: '100.50',
381
+ })
382
+
383
+ console.log(`Bridge deposit submitted: ${bridgeDeposit.execId}`)
384
+
385
+ // Cross-chain Earn deposits currently support Ethereum Sepolia, Arbitrum
386
+ // Sepolia, and Base Sepolia as sources, with Arc Testnet as the Earn
387
+ // destination.
388
+
370
389
  // Query a vault position
371
390
  const position = await kit.earn.getPosition({
372
391
  from: { adapter, chain: EarnChain.Arc_Testnet },
@@ -380,6 +399,10 @@ await kit.earn.claimRewards({
380
399
  })
381
400
  ```
382
401
 
402
+ Same-chain Earn deposits keep the existing transaction result. Cross-chain Earn
403
+ deposits return bridge submission details such as `execId`, `status`, and
404
+ `expiresAt`.
405
+
383
406
  For the full Earn API, see the [`@circle-fin/earn-kit` README](../earn-kit/README.md).
384
407
 
385
408
  ## Configuration