pods-sdk 0.2.58
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +760 -0
- package/dist/api/actions.api.d.ts +433 -0
- package/dist/api/actions.api.d.ts.map +1 -0
- package/dist/api/history.api.d.ts +311 -0
- package/dist/api/history.api.d.ts.map +1 -0
- package/dist/api/tokens.api.d.ts +985 -0
- package/dist/api/tokens.api.d.ts.map +1 -0
- package/dist/components/earn/GroupedStrategyList.d.ts +21 -0
- package/dist/components/earn/GroupedStrategyList.d.ts.map +1 -0
- package/dist/components/earn/StrategyDetailsView.d.ts +14 -0
- package/dist/components/earn/StrategyDetailsView.d.ts.map +1 -0
- package/dist/components/earn/desktop/EarnPageDesktop.d.ts +13 -0
- package/dist/components/earn/desktop/EarnPageDesktop.d.ts.map +1 -0
- package/dist/components/earn/desktop/ExploreStrategiesGrid.d.ts +30 -0
- package/dist/components/earn/desktop/ExploreStrategiesGrid.d.ts.map +1 -0
- package/dist/components/earn/desktop/InvestedStrategiesSection.d.ts +22 -0
- package/dist/components/earn/desktop/InvestedStrategiesSection.d.ts.map +1 -0
- package/dist/components/earn/desktop/InvestmentSummaryDesktop.d.ts +27 -0
- package/dist/components/earn/desktop/InvestmentSummaryDesktop.d.ts.map +1 -0
- package/dist/components/earn/desktop/RecentTransactions.d.ts +32 -0
- package/dist/components/earn/desktop/RecentTransactions.d.ts.map +1 -0
- package/dist/components/earn/desktop/StrategyGridCard.d.ts +35 -0
- package/dist/components/earn/desktop/StrategyGridCard.d.ts.map +1 -0
- package/dist/constants/analytics.d.ts +92 -0
- package/dist/constants/analytics.d.ts.map +1 -0
- package/dist/constants/error-monitoring.d.ts +2 -0
- package/dist/constants/error-monitoring.d.ts.map +1 -0
- package/dist/domain/swap/deriveAmountInForSwap.d.ts +11 -0
- package/dist/domain/swap/deriveAmountInForSwap.d.ts.map +1 -0
- package/dist/domain/swap/deriveTokenPriceUSD.d.ts +10 -0
- package/dist/domain/swap/deriveTokenPriceUSD.d.ts.map +1 -0
- package/dist/domain/swap/getAmountInUSD.d.ts +12 -0
- package/dist/domain/swap/getAmountInUSD.d.ts.map +1 -0
- package/dist/domain/swap/getQuoteOutputUI.d.ts +14 -0
- package/dist/domain/swap/getQuoteOutputUI.d.ts.map +1 -0
- package/dist/domain/swap/getQuoteOutputUSD.d.ts +12 -0
- package/dist/domain/swap/getQuoteOutputUSD.d.ts.map +1 -0
- package/dist/domain/swap/index.d.ts +11 -0
- package/dist/domain/swap/index.d.ts.map +1 -0
- package/dist/domain/swap/isPositiveNumberString.d.ts +5 -0
- package/dist/domain/swap/isPositiveNumberString.d.ts.map +1 -0
- package/dist/domain/swap/isQuoteMatchingInput.d.ts +24 -0
- package/dist/domain/swap/isQuoteMatchingInput.d.ts.map +1 -0
- package/dist/domain/swap/normalizeSwapAddress.d.ts +6 -0
- package/dist/domain/swap/normalizeSwapAddress.d.ts.map +1 -0
- package/dist/domain/swap/resolveEffectivePrice.d.ts +14 -0
- package/dist/domain/swap/resolveEffectivePrice.d.ts.map +1 -0
- package/dist/domain/swap/resolveInputAmountBase.d.ts +11 -0
- package/dist/domain/swap/resolveInputAmountBase.d.ts.map +1 -0
- package/dist/hooks/useAnalytics.d.ts +9 -0
- package/dist/hooks/useAnalytics.d.ts.map +1 -0
- package/dist/hooks/useDimensions.d.ts +15 -0
- package/dist/hooks/useDimensions.d.ts.map +1 -0
- package/dist/hooks/useGlobalCurrency.d.ts +17 -0
- package/dist/hooks/useGlobalCurrency.d.ts.map +1 -0
- package/dist/hooks/useGlobalHistory.d.ts +22 -0
- package/dist/hooks/useGlobalHistory.d.ts.map +1 -0
- package/dist/hooks/useGroupedStrategies.d.ts +4 -0
- package/dist/hooks/useGroupedStrategies.d.ts.map +1 -0
- package/dist/hooks/useI18n.d.ts +12 -0
- package/dist/hooks/useI18n.d.ts.map +1 -0
- package/dist/hooks/useStrategyTokens.d.ts +15 -0
- package/dist/hooks/useStrategyTokens.d.ts.map +1 -0
- package/dist/hooks/useSwapFlowLogic.d.ts +198 -0
- package/dist/hooks/useSwapFlowLogic.d.ts.map +1 -0
- package/dist/hooks/useTokenGroups.d.ts +14 -0
- package/dist/hooks/useTokenGroups.d.ts.map +1 -0
- package/dist/i18n/index.d.ts +13 -0
- package/dist/i18n/index.d.ts.map +1 -0
- package/dist/i18n/messages.d.ts +307 -0
- package/dist/i18n/messages.d.ts.map +1 -0
- package/dist/pages/SwapFlow/SwapFormContext.d.ts +6 -0
- package/dist/pages/SwapFlow/SwapFormContext.d.ts.map +1 -0
- package/dist/pages/SwapFlow/SwapHistoryScreen.d.ts +4 -0
- package/dist/pages/SwapFlow/SwapHistoryScreen.d.ts.map +1 -0
- package/dist/pages/TransactionProcessingDetails/StepDisplay.d.ts +10 -0
- package/dist/pages/TransactionProcessingDetails/StepDisplay.d.ts.map +1 -0
- package/dist/pages/TransactionProcessingDetails/StepStatusIcon.d.ts +11 -0
- package/dist/pages/TransactionProcessingDetails/StepStatusIcon.d.ts.map +1 -0
- package/dist/pages/TransactionProcessingDetails/StepStatusText.d.ts +10 -0
- package/dist/pages/TransactionProcessingDetails/StepStatusText.d.ts.map +1 -0
- package/dist/pages/TransactionProcessingDetails/index.d.ts +4 -0
- package/dist/pages/TransactionProcessingDetails/index.d.ts.map +1 -0
- package/dist/pages/TransactionProcessingDetails.d.ts +22 -0
- package/dist/pages/TransactionProcessingDetails.d.ts.map +1 -0
- package/dist/pages/TransactionStepValue.d.ts +12 -0
- package/dist/pages/TransactionStepValue.d.ts.map +1 -0
- package/dist/services/analyticsService.d.ts +11 -0
- package/dist/services/analyticsService.d.ts.map +1 -0
- package/dist/services/errorMonitoringService.d.ts +17 -0
- package/dist/services/errorMonitoringService.d.ts.map +1 -0
- package/dist/services/scrubPii.d.ts +3 -0
- package/dist/services/scrubPii.d.ts.map +1 -0
- package/dist/test-utils/grouped-strategies-dummy.d.ts +6 -0
- package/dist/test-utils/grouped-strategies-dummy.d.ts.map +1 -0
- package/dist/test-utils/history-dummy.d.ts +34 -0
- package/dist/test-utils/history-dummy.d.ts.map +1 -0
- package/dist/test-utils/investment-summary-dummy.d.ts +17 -0
- package/dist/test-utils/investment-summary-dummy.d.ts.map +1 -0
- package/dist/test-utils/strategies-dummy.d.ts +8 -0
- package/dist/test-utils/strategies-dummy.d.ts.map +1 -0
- package/dist/test-utils/strategies-with-apy-dummy.d.ts +32 -0
- package/dist/test-utils/strategies-with-apy-dummy.d.ts.map +1 -0
- package/dist/test-utils/swap-dummy.d.ts +35 -0
- package/dist/test-utils/swap-dummy.d.ts.map +1 -0
- package/dist/test-utils/swap-form-view-dummy.d.ts +21 -0
- package/dist/test-utils/swap-form-view-dummy.d.ts.map +1 -0
- package/dist/types/analytics.d.ts +17 -0
- package/dist/types/analytics.d.ts.map +1 -0
- package/dist/types/currency.d.ts +2 -0
- package/dist/types/currency.d.ts.map +1 -0
- package/dist/types/dimensions.d.ts +7 -0
- package/dist/types/dimensions.d.ts.map +1 -0
- package/dist/types/grouped-strategies.d.ts +42 -0
- package/dist/types/grouped-strategies.d.ts.map +1 -0
- package/dist/types/sdk-error-context.d.ts +10 -0
- package/dist/types/sdk-error-context.d.ts.map +1 -0
- package/dist/types/strategy-with-apy.d.ts +8 -0
- package/dist/types/strategy-with-apy.d.ts.map +1 -0
- package/dist/types/tokengroups.d.ts +47 -0
- package/dist/types/tokengroups.d.ts.map +1 -0
- package/dist/types/transaction.d.ts +14 -0
- package/dist/types/transaction.d.ts.map +1 -0
- package/dist/ui/action-sheet/ChooseAStrategyActionsheetView.d.ts +14 -0
- package/dist/ui/action-sheet/ChooseAStrategyActionsheetView.d.ts.map +1 -0
- package/dist/ui/action-sheet/ChooseWithdrawAssetActionsheet.d.ts +16 -0
- package/dist/ui/action-sheet/ChooseWithdrawAssetActionsheet.d.ts.map +1 -0
- package/dist/ui/chip/Chip.d.ts +30 -0
- package/dist/ui/chip/Chip.d.ts.map +1 -0
- package/dist/ui/chip/ChipGroup.d.ts +43 -0
- package/dist/ui/chip/ChipGroup.d.ts.map +1 -0
- package/dist/ui/chip/index.d.ts +5 -0
- package/dist/ui/chip/index.d.ts.map +1 -0
- package/dist/ui/group-label/GroupLabel.d.ts +17 -0
- package/dist/ui/group-label/GroupLabel.d.ts.map +1 -0
- package/dist/ui/group-label/index.d.ts +3 -0
- package/dist/ui/group-label/index.d.ts.map +1 -0
- package/dist/ui/loading/LoadingDots.d.ts +11 -0
- package/dist/ui/loading/LoadingDots.d.ts.map +1 -0
- package/dist/ui/loading/index.d.ts +2 -0
- package/dist/ui/loading/index.d.ts.map +1 -0
- package/dist/ui/swap-form/SwapAdvancedSettings.d.ts +9 -0
- package/dist/ui/swap-form/SwapAdvancedSettings.d.ts.map +1 -0
- package/dist/ui/swap-form/SwapAmountInputView.d.ts +11 -0
- package/dist/ui/swap-form/SwapAmountInputView.d.ts.map +1 -0
- package/dist/ui/swap-form/SwapNetworkSelectorView.d.ts +10 -0
- package/dist/ui/swap-form/SwapNetworkSelectorView.d.ts.map +1 -0
- package/dist/ui/swap-form/SwapOutputAmountView.d.ts +8 -0
- package/dist/ui/swap-form/SwapOutputAmountView.d.ts.map +1 -0
- package/dist/ui/swap-form/SwapQuoteBlockchainCostsView.d.ts +9 -0
- package/dist/ui/swap-form/SwapQuoteBlockchainCostsView.d.ts.map +1 -0
- package/dist/ui/swap-form/SwapQuoteErrorsView.d.ts +7 -0
- package/dist/ui/swap-form/SwapQuoteErrorsView.d.ts.map +1 -0
- package/dist/ui/swap-form/SwapQuoteHeaderView.d.ts +7 -0
- package/dist/ui/swap-form/SwapQuoteHeaderView.d.ts.map +1 -0
- package/dist/ui/swap-form/SwapSlippageToleranceButtonsView.d.ts +7 -0
- package/dist/ui/swap-form/SwapSlippageToleranceButtonsView.d.ts.map +1 -0
- package/dist/ui/swap-form/SwapTokenSelectorView.d.ts +11 -0
- package/dist/ui/swap-form/SwapTokenSelectorView.d.ts.map +1 -0
- package/dist/ui/swap-form/SwapTransactionDetails.d.ts +6 -0
- package/dist/ui/swap-form/SwapTransactionDetails.d.ts.map +1 -0
- package/dist/ui/transaction-screen/history/HistoryDepositDetailsView.d.ts +25 -0
- package/dist/ui/transaction-screen/history/HistoryDepositDetailsView.d.ts.map +1 -0
- package/dist/ui/transaction-screen/history/HistoryDetailsNotFound.d.ts +5 -0
- package/dist/ui/transaction-screen/history/HistoryDetailsNotFound.d.ts.map +1 -0
- package/dist/ui/transaction-screen/history/HistorySwapDetailsScreen.d.ts +8 -0
- package/dist/ui/transaction-screen/history/HistorySwapDetailsScreen.d.ts.map +1 -0
- package/dist/ui/transaction-screen/history/HistoryWithdrawDetailsView.d.ts +5 -0
- package/dist/ui/transaction-screen/history/HistoryWithdrawDetailsView.d.ts.map +1 -0
- package/dist/ui/transaction-screen/swap/SwapCrossChainProcessingScreen.d.ts +3 -0
- package/dist/ui/transaction-screen/swap/SwapCrossChainProcessingScreen.d.ts.map +1 -0
- package/dist/ui/transaction-screen/withdraw/WithdrawSuccess.d.ts +24 -0
- package/dist/ui/transaction-screen/withdraw/WithdrawSuccess.d.ts.map +1 -0
- package/dist/utils/addressUtils.d.ts +7 -0
- package/dist/utils/addressUtils.d.ts.map +1 -0
- package/dist/utils/analytics.d.ts +5 -0
- package/dist/utils/analytics.d.ts.map +1 -0
- package/dist/utils/currency.d.ts +11 -0
- package/dist/utils/currency.d.ts.map +1 -0
- package/dist/utils/errorMapping.d.ts +19 -0
- package/dist/utils/errorMapping.d.ts.map +1 -0
- package/dist/utils/filterStrategies.d.ts +21 -0
- package/dist/utils/filterStrategies.d.ts.map +1 -0
- package/dist/utils/fontLoader.d.ts +9 -0
- package/dist/utils/fontLoader.d.ts.map +1 -0
- package/dist/utils/historyMappers.d.ts +71 -0
- package/dist/utils/historyMappers.d.ts.map +1 -0
- package/dist/utils/strategyCategories.d.ts +25 -0
- package/dist/utils/strategyCategories.d.ts.map +1 -0
- package/dist/utils/tokenSorting.d.ts +30 -0
- package/dist/utils/tokenSorting.d.ts.map +1 -0
- package/dist/utils/tokengroups.d.ts +11 -0
- package/dist/utils/tokengroups.d.ts.map +1 -0
- package/package.json +132 -0
package/README.md
ADDED
|
@@ -0,0 +1,760 @@
|
|
|
1
|
+
# Deframe SDK
|
|
2
|
+
|
|
3
|
+
React widgets for DeFi earn and swap flows
|
|
4
|
+
|
|
5
|
+
This package ships two host-rendered widgets:
|
|
6
|
+
- `EarnWidget`
|
|
7
|
+
- `SwapWidget`
|
|
8
|
+
|
|
9
|
+
The host application owns wallet connection, signing, and transaction submission through `processBytecode`.
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
# pnpm
|
|
15
|
+
pnpm add deframe-sdk
|
|
16
|
+
# npm
|
|
17
|
+
npm install deframe-sdk
|
|
18
|
+
# yarn
|
|
19
|
+
yarn add deframe-sdk
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Notes:
|
|
23
|
+
- Use only the production npm package: `deframe-sdk` ([npm](https://www.npmjs.com/package/deframe-sdk)).
|
|
24
|
+
- No local/workspace/file dependency references are required for host integration.
|
|
25
|
+
- Keep `react` and `react-dom` installed in the host app.
|
|
26
|
+
- `deframe-sdk` loads widget styles from its entrypoint. No separate CSS import is required for the default setup.
|
|
27
|
+
|
|
28
|
+
## Vite: Single React Instance (important for linked/local packages)
|
|
29
|
+
|
|
30
|
+
If your app consumes SDK packages via `file:`, workspace links, or symlinks, multiple React copies can be resolved at runtime.
|
|
31
|
+
That can cause `Invalid hook call` errors (for example: `Cannot read properties of null (reading 'useEffect')`).
|
|
32
|
+
|
|
33
|
+
Use this Vite config to force one React instance across app + linked packages:
|
|
34
|
+
|
|
35
|
+
```ts
|
|
36
|
+
import path from 'node:path'
|
|
37
|
+
import { defineConfig } from 'vite'
|
|
38
|
+
import react from '@vitejs/plugin-react'
|
|
39
|
+
|
|
40
|
+
export default defineConfig({
|
|
41
|
+
plugins: [react()],
|
|
42
|
+
resolve: {
|
|
43
|
+
dedupe: ['react', 'react-dom'],
|
|
44
|
+
alias: {
|
|
45
|
+
react: path.resolve(__dirname, 'node_modules/react'),
|
|
46
|
+
'react-dom': path.resolve(__dirname, 'node_modules/react-dom'),
|
|
47
|
+
'react/jsx-runtime': path.resolve(__dirname, 'node_modules/react/jsx-runtime.js'),
|
|
48
|
+
'react/jsx-dev-runtime': path.resolve(__dirname, 'node_modules/react/jsx-dev-runtime.js'),
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
optimizeDeps: {
|
|
52
|
+
// Avoid manual .vite cache cleanup in linked-package setups.
|
|
53
|
+
force: true,
|
|
54
|
+
},
|
|
55
|
+
})
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
With this config in place, you should not need manual `rm -rf node_modules/.vite` or manual restart instructions in your integration flow.
|
|
59
|
+
|
|
60
|
+
## CSS Isolation (Host Shell vs Widget)
|
|
61
|
+
|
|
62
|
+
The SDK widgets are designed to be embedded into existing apps without taking over host styling.
|
|
63
|
+
|
|
64
|
+
Use this isolation model:
|
|
65
|
+
|
|
66
|
+
- Keep host/shell styles scoped to your own container (example: `.host-shell ...`).
|
|
67
|
+
- Treat `.deframe-widget` as a style boundary owned by the SDK.
|
|
68
|
+
- Avoid global resets that can leak into third-party widgets:
|
|
69
|
+
- `* { ... }`
|
|
70
|
+
- `div, button, input { ... }`
|
|
71
|
+
- global `all: initial` / aggressive normalize rules on app-wide containers.
|
|
72
|
+
- Use `DeframeProvider` `config.theme` as the source of truth for widget theme (`mode`, `preset`, `overrides`).
|
|
73
|
+
- Do not rely on ad-hoc utility-class overrides inside widget internals except as temporary debug workarounds.
|
|
74
|
+
|
|
75
|
+
Recommended host layout:
|
|
76
|
+
|
|
77
|
+
```tsx
|
|
78
|
+
<main className="host-shell">
|
|
79
|
+
{/* host UI */}
|
|
80
|
+
<section className="widget-slot">
|
|
81
|
+
<EarnWidget autoHeight />
|
|
82
|
+
</section>
|
|
83
|
+
</main>
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
```css
|
|
87
|
+
.host-shell {
|
|
88
|
+
/* your app styles */
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.widget-slot {
|
|
92
|
+
/* spacing, border, layout only */
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Reference widget-only variable block (generic dark/default preset, client-agnostic):
|
|
97
|
+
|
|
98
|
+
```css
|
|
99
|
+
/* Scope to widget only. Do not apply globally. */
|
|
100
|
+
.host-shell .deframe-widget {
|
|
101
|
+
--deframe-brand-primary: #405eff;
|
|
102
|
+
--deframe-brand-secondary: #a9abf7;
|
|
103
|
+
--deframe-bg-default: #121212;
|
|
104
|
+
--deframe-bg-subtle: #1e1e1e;
|
|
105
|
+
--deframe-bg-muted: #2c2c2c;
|
|
106
|
+
--deframe-bg-raised: #232323;
|
|
107
|
+
--deframe-bg-inverse: #ffffff;
|
|
108
|
+
--deframe-text-primary: #ffffff;
|
|
109
|
+
--deframe-text-secondary: #e3e4e8;
|
|
110
|
+
--deframe-text-disabled: #898d95;
|
|
111
|
+
--deframe-text-inverse: #252050;
|
|
112
|
+
--deframe-state-success: #2ba176;
|
|
113
|
+
--deframe-state-error: #ff4d4f;
|
|
114
|
+
--deframe-state-warning: #f6a700;
|
|
115
|
+
|
|
116
|
+
/* Important fallbacks to avoid light cards in dark mode */
|
|
117
|
+
--color-bg-raised: var(--deframe-bg-raised, #232323);
|
|
118
|
+
--color-brand-tint: #1e1e3f;
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Generic preset recommendation:
|
|
123
|
+
|
|
124
|
+
```ts
|
|
125
|
+
theme: {
|
|
126
|
+
mode: 'dark',
|
|
127
|
+
preset: 'default',
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Use `preset: 'cryptocontrol'` only when you intentionally want that brand style.
|
|
132
|
+
|
|
133
|
+
If you need hard guarantees in high-risk host environments, use one of:
|
|
134
|
+
|
|
135
|
+
- Dedicated iframe container for the widget.
|
|
136
|
+
- Shadow DOM boundary around the widget mount point.
|
|
137
|
+
|
|
138
|
+
## Environment Variables
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
NEXT_PUBLIC_DEFRAME_API_URL=https://api.deframe.com
|
|
142
|
+
NEXT_PUBLIC_DEFRAME_API_KEY=your_deframe_api_key
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Canonical env forms for host integrations:
|
|
146
|
+
- public client:
|
|
147
|
+
- `NEXT_PUBLIC_DEFRAME_API_URL`
|
|
148
|
+
- `NEXT_PUBLIC_DEFRAME_API_KEY`
|
|
149
|
+
- server/internal:
|
|
150
|
+
- `DEFRAME_API_URL`
|
|
151
|
+
- `DEFRAME_API_KEY`
|
|
152
|
+
- if API URL is not set in some internal hosts, default to `https://api.deframe.com` (where applicable).
|
|
153
|
+
|
|
154
|
+
## Core Integration
|
|
155
|
+
|
|
156
|
+
### 1) Wrap your widget tree with `DeframeProvider`
|
|
157
|
+
|
|
158
|
+
```tsx
|
|
159
|
+
'use client'
|
|
160
|
+
|
|
161
|
+
import { ReactNode, useMemo } from 'react'
|
|
162
|
+
import { DeframeProvider, type UpdateTxStatus } from 'deframe-sdk'
|
|
163
|
+
|
|
164
|
+
type BytecodeTransaction = {
|
|
165
|
+
chainId?: number
|
|
166
|
+
to: string
|
|
167
|
+
data: string
|
|
168
|
+
value: string
|
|
169
|
+
gasLimit?: string
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
type ProcessBytecode = (
|
|
173
|
+
payload: { clientTxId: string; bytecodes: BytecodeTransaction[]; simulateError?: boolean },
|
|
174
|
+
ctx: { updateTxStatus: UpdateTxStatus }
|
|
175
|
+
) => void | Promise<void>
|
|
176
|
+
|
|
177
|
+
export function DeframeHostProvider({
|
|
178
|
+
children,
|
|
179
|
+
walletAddress,
|
|
180
|
+
userId,
|
|
181
|
+
globalCurrency,
|
|
182
|
+
globalCurrencyExchangeRate,
|
|
183
|
+
processBytecode,
|
|
184
|
+
}: {
|
|
185
|
+
children: ReactNode
|
|
186
|
+
walletAddress: string
|
|
187
|
+
userId?: string
|
|
188
|
+
globalCurrency?: 'USD' | 'BRL'
|
|
189
|
+
globalCurrencyExchangeRate?: number
|
|
190
|
+
processBytecode: ProcessBytecode
|
|
191
|
+
}) {
|
|
192
|
+
const config = useMemo(() => ({
|
|
193
|
+
DEFRAME_API_URL: process.env.NEXT_PUBLIC_DEFRAME_API_URL,
|
|
194
|
+
DEFRAME_API_KEY: process.env.NEXT_PUBLIC_DEFRAME_API_KEY,
|
|
195
|
+
walletAddress,
|
|
196
|
+
userId,
|
|
197
|
+
globalCurrency,
|
|
198
|
+
globalCurrencyExchangeRate,
|
|
199
|
+
strategiesLimit: 50,
|
|
200
|
+
debug: process.env.NODE_ENV !== 'production',
|
|
201
|
+
theme: {
|
|
202
|
+
mode: 'dark' as const,
|
|
203
|
+
preset: 'cryptocontrol' as const,
|
|
204
|
+
},
|
|
205
|
+
}), [walletAddress, userId, globalCurrency, globalCurrencyExchangeRate])
|
|
206
|
+
|
|
207
|
+
return (
|
|
208
|
+
<DeframeProvider config={config} processBytecode={processBytecode}>
|
|
209
|
+
{children}
|
|
210
|
+
</DeframeProvider>
|
|
211
|
+
)
|
|
212
|
+
}
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### 2) Render `EarnWidget`
|
|
216
|
+
|
|
217
|
+
```tsx
|
|
218
|
+
'use client'
|
|
219
|
+
|
|
220
|
+
import { useState } from 'react'
|
|
221
|
+
import { EarnWidget } from 'deframe-sdk'
|
|
222
|
+
|
|
223
|
+
export function EarnPage() {
|
|
224
|
+
const [routeName, setRouteName] = useState('overview')
|
|
225
|
+
const isOverview = routeName === 'overview'
|
|
226
|
+
|
|
227
|
+
return (
|
|
228
|
+
<div className={`w-full mx-auto ${isOverview ? 'lg:p-12' : 'lg:p-6'}`}>
|
|
229
|
+
<div className={`w-full mx-auto ${isOverview ? 'max-w-[1400px]' : 'max-w-[620px]'}`}>
|
|
230
|
+
<EarnWidget autoHeight onRouteChange={setRouteName} />
|
|
231
|
+
</div>
|
|
232
|
+
</div>
|
|
233
|
+
)
|
|
234
|
+
}
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### 3) Render `SwapWidget` with optional prefilled params
|
|
238
|
+
|
|
239
|
+
```tsx
|
|
240
|
+
'use client'
|
|
241
|
+
|
|
242
|
+
import { useMemo } from 'react'
|
|
243
|
+
import { useSearchParams } from 'next/navigation'
|
|
244
|
+
import { SwapWidget } from 'deframe-sdk'
|
|
245
|
+
|
|
246
|
+
export function SwapPage() {
|
|
247
|
+
const searchParams = useSearchParams()
|
|
248
|
+
|
|
249
|
+
const toTokenAddress = searchParams.get('toTokenAddress') ?? undefined
|
|
250
|
+
const toChainId = searchParams.get('toChainId') ? Number(searchParams.get('toChainId')) : undefined
|
|
251
|
+
const fromTokenAddress = searchParams.get('fromTokenAddress') ?? undefined
|
|
252
|
+
const fromChainId = searchParams.get('fromChainId') ? Number(searchParams.get('fromChainId')) : undefined
|
|
253
|
+
|
|
254
|
+
const widgetProps = useMemo(() => {
|
|
255
|
+
const props: {
|
|
256
|
+
height: string
|
|
257
|
+
toTokenAddress?: string
|
|
258
|
+
toChainId?: number
|
|
259
|
+
fromTokenAddress?: string
|
|
260
|
+
fromChainId?: number
|
|
261
|
+
} = {
|
|
262
|
+
height: '800px',
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
if (toTokenAddress) props.toTokenAddress = toTokenAddress
|
|
266
|
+
if (toChainId) props.toChainId = toChainId
|
|
267
|
+
if (fromTokenAddress) props.fromTokenAddress = fromTokenAddress
|
|
268
|
+
if (fromChainId) props.fromChainId = fromChainId
|
|
269
|
+
|
|
270
|
+
return props
|
|
271
|
+
}, [toTokenAddress, toChainId, fromTokenAddress, fromChainId])
|
|
272
|
+
|
|
273
|
+
const widgetKey = `${toTokenAddress}-${toChainId}-${fromTokenAddress}-${fromChainId}`
|
|
274
|
+
|
|
275
|
+
return <SwapWidget key={widgetKey} {...widgetProps} />
|
|
276
|
+
}
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
## Widget-to-Host Events
|
|
280
|
+
This README keeps the working route pattern loop-safe for existing Privy-based implementations:
|
|
281
|
+
|
|
282
|
+
Use `EarnWidget` `onRouteChange` prop to keep lightweight host routing state:
|
|
283
|
+
- `history` -> `/dashboard/history`
|
|
284
|
+
- `wallet` -> `/dashboard`
|
|
285
|
+
- `swap` -> `/dashboard/swap`
|
|
286
|
+
- `earn` -> `/dashboard/earn`
|
|
287
|
+
|
|
288
|
+
`useDeframe().addEventListener` route handlers are intentionally omitted here because they caused host loops in some integrations.
|
|
289
|
+
|
|
290
|
+
## `processBytecode` contract
|
|
291
|
+
|
|
292
|
+
The host must execute `bytecodes` and report lifecycle updates with `ctx.updateTxStatus(...)`.
|
|
293
|
+
|
|
294
|
+
Payload shape is:
|
|
295
|
+
|
|
296
|
+
```ts
|
|
297
|
+
type TxIntent = {
|
|
298
|
+
clientTxId: string
|
|
299
|
+
bytecodes: Array<{ chainId?: number; to: string; data: string; value: string; gasLimit?: string }>
|
|
300
|
+
simulateError?: boolean
|
|
301
|
+
}
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
### Required success path statuses
|
|
305
|
+
- `HOST_ACK`
|
|
306
|
+
- `SIGNATURE_PROMPTED`
|
|
307
|
+
- `TX_SUBMITTED`
|
|
308
|
+
- `TX_CONFIRMED`
|
|
309
|
+
- `TX_FINALIZED`
|
|
310
|
+
- include `txHash` when available on `TX_SUBMITTED` and `TX_CONFIRMED` if you have it
|
|
311
|
+
|
|
312
|
+
### Required error statuses
|
|
313
|
+
- `SIGNATURE_DECLINED`
|
|
314
|
+
- `SIGNATURE_ERROR`
|
|
315
|
+
- `TX_REVERTED`
|
|
316
|
+
- `TX_FAILED` (supported)
|
|
317
|
+
|
|
318
|
+
### Optional advanced statuses
|
|
319
|
+
- `TX_REPLACED`
|
|
320
|
+
- `TX_DROPPED`
|
|
321
|
+
- `SWAP_CROSSCHAIN_DESTINATION_CONFIRMED`
|
|
322
|
+
|
|
323
|
+
When `SIGNATURE_PROMPTED` is emitted, you typically call the wallet signer next.
|
|
324
|
+
Map wallet refusal codes/messages to:
|
|
325
|
+
- `SIGNATURE_DECLINED` for user cancellation (`4001`, `ACTION_REJECTED`).
|
|
326
|
+
- `SIGNATURE_ERROR` for other thrown errors before submission.
|
|
327
|
+
|
|
328
|
+
### SDK default fallback (no `processBytecode`)
|
|
329
|
+
|
|
330
|
+
- If you run without a `processBytecode` prop, Deframe falls back to:
|
|
331
|
+
- `window.parent.postMessage({ type: 'REQUEST_SIGNATURE', clientTxId, bytecodes })`
|
|
332
|
+
- Keep this as a compatibility path only if your host is already wired to that message bridge.
|
|
333
|
+
|
|
334
|
+
### Minimal host implementation
|
|
335
|
+
|
|
336
|
+
```ts
|
|
337
|
+
export const processBytecode = async (
|
|
338
|
+
payload: {
|
|
339
|
+
clientTxId: string
|
|
340
|
+
bytecodes: Array<{ chainId?: number; to: string; data: string; value: string; gasLimit?: string }>
|
|
341
|
+
},
|
|
342
|
+
ctx: {
|
|
343
|
+
updateTxStatus: (event: any) => void
|
|
344
|
+
}
|
|
345
|
+
) => {
|
|
346
|
+
const { clientTxId, bytecodes } = payload
|
|
347
|
+
|
|
348
|
+
try {
|
|
349
|
+
ctx.updateTxStatus({ type: 'HOST_ACK', clientTxId })
|
|
350
|
+
|
|
351
|
+
for (const tx of bytecodes) {
|
|
352
|
+
ctx.updateTxStatus({ type: 'SIGNATURE_PROMPTED', clientTxId })
|
|
353
|
+
|
|
354
|
+
// 1) sign + send transaction in your wallet stack
|
|
355
|
+
// 2) get tx hash
|
|
356
|
+
const txHash = await sendTransactionWithYourWallet(tx)
|
|
357
|
+
|
|
358
|
+
ctx.updateTxStatus({ type: 'TX_SUBMITTED', clientTxId, chainId: tx.chainId, txHash })
|
|
359
|
+
|
|
360
|
+
// Wait until mined/confirmed
|
|
361
|
+
await waitForConfirmation(txHash)
|
|
362
|
+
ctx.updateTxStatus({ type: 'TX_CONFIRMED', clientTxId, txHash })
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
ctx.updateTxStatus({ type: 'TX_FINALIZED', clientTxId })
|
|
366
|
+
} catch (error: any) {
|
|
367
|
+
const code = error?.code
|
|
368
|
+
const message = error?.message || 'Transaction failed'
|
|
369
|
+
|
|
370
|
+
if (code === 4001 || code === 'ACTION_REJECTED' || String(message).includes('rejected')) {
|
|
371
|
+
ctx.updateTxStatus({ type: 'SIGNATURE_DECLINED', clientTxId })
|
|
372
|
+
return
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
ctx.updateTxStatus({
|
|
376
|
+
type: 'SIGNATURE_ERROR',
|
|
377
|
+
clientTxId,
|
|
378
|
+
code: String(code || 'UNKNOWN_ERROR'),
|
|
379
|
+
message,
|
|
380
|
+
})
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
## Dynamic Integration (React)
|
|
386
|
+
|
|
387
|
+
### Install
|
|
388
|
+
|
|
389
|
+
```bash
|
|
390
|
+
pnpm add @dynamic-labs/sdk-react-core @dynamic-labs/ethereum viem
|
|
391
|
+
# or npm/yarn equivalents
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
### Provider setup
|
|
395
|
+
|
|
396
|
+
```tsx
|
|
397
|
+
'use client'
|
|
398
|
+
|
|
399
|
+
import { DynamicContextProvider } from '@dynamic-labs/sdk-react-core'
|
|
400
|
+
import { EthereumWalletConnectors } from '@dynamic-labs/ethereum'
|
|
401
|
+
|
|
402
|
+
export function DynamicProviders({ children }: { children: React.ReactNode }) {
|
|
403
|
+
return (
|
|
404
|
+
<DynamicContextProvider
|
|
405
|
+
settings={{
|
|
406
|
+
environmentId: process.env.NEXT_PUBLIC_DYNAMIC_ENV_ID!,
|
|
407
|
+
walletConnectors: [EthereumWalletConnectors],
|
|
408
|
+
}}
|
|
409
|
+
>
|
|
410
|
+
{children}
|
|
411
|
+
</DynamicContextProvider>
|
|
412
|
+
)
|
|
413
|
+
}
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
### `processBytecode` using Dynamic `primaryWallet`
|
|
417
|
+
|
|
418
|
+
```tsx
|
|
419
|
+
'use client'
|
|
420
|
+
|
|
421
|
+
import { useDynamicContext } from '@dynamic-labs/sdk-react-core'
|
|
422
|
+
|
|
423
|
+
type Bytecode = { chainId?: number; to: string; data: string; value: string }
|
|
424
|
+
|
|
425
|
+
export function useDynamicDeframeProcessBytecode() {
|
|
426
|
+
const { primaryWallet } = useDynamicContext()
|
|
427
|
+
|
|
428
|
+
return async (
|
|
429
|
+
payload: { clientTxId: string; bytecodes: Bytecode[] },
|
|
430
|
+
ctx: { updateTxStatus: (event: any) => void }
|
|
431
|
+
) => {
|
|
432
|
+
const { clientTxId, bytecodes } = payload
|
|
433
|
+
|
|
434
|
+
if (!primaryWallet) {
|
|
435
|
+
ctx.updateTxStatus({
|
|
436
|
+
type: 'SIGNATURE_ERROR',
|
|
437
|
+
clientTxId,
|
|
438
|
+
code: 'NO_WALLET',
|
|
439
|
+
message: 'No connected Dynamic wallet',
|
|
440
|
+
})
|
|
441
|
+
return
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
try {
|
|
445
|
+
ctx.updateTxStatus({ type: 'HOST_ACK', clientTxId })
|
|
446
|
+
|
|
447
|
+
for (const tx of bytecodes) {
|
|
448
|
+
if (tx.chainId && primaryWallet.connector.supportsNetworkSwitching?.()) {
|
|
449
|
+
await primaryWallet.switchNetwork(tx.chainId)
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
ctx.updateTxStatus({ type: 'SIGNATURE_PROMPTED', clientTxId })
|
|
453
|
+
|
|
454
|
+
const walletClient = await primaryWallet.connector.getWalletClient()
|
|
455
|
+
const txHash = await walletClient.sendTransaction({
|
|
456
|
+
account: primaryWallet.address as `0x${string}`,
|
|
457
|
+
to: tx.to as `0x${string}`,
|
|
458
|
+
data: tx.data as `0x${string}`,
|
|
459
|
+
value: BigInt(tx.value || '0'),
|
|
460
|
+
})
|
|
461
|
+
|
|
462
|
+
ctx.updateTxStatus({
|
|
463
|
+
type: 'TX_SUBMITTED',
|
|
464
|
+
clientTxId,
|
|
465
|
+
chainId: tx.chainId,
|
|
466
|
+
txHash,
|
|
467
|
+
})
|
|
468
|
+
|
|
469
|
+
const publicClient = primaryWallet.connector.getPublicClient?.()
|
|
470
|
+
if (publicClient) {
|
|
471
|
+
await publicClient.waitForTransactionReceipt({ hash: txHash })
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
ctx.updateTxStatus({ type: 'TX_CONFIRMED', clientTxId, txHash })
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
ctx.updateTxStatus({ type: 'TX_FINALIZED', clientTxId })
|
|
478
|
+
} catch (error: any) {
|
|
479
|
+
if (error?.code === 4001 || error?.code === 'ACTION_REJECTED') {
|
|
480
|
+
ctx.updateTxStatus({ type: 'SIGNATURE_DECLINED', clientTxId })
|
|
481
|
+
return
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
ctx.updateTxStatus({
|
|
485
|
+
type: 'SIGNATURE_ERROR',
|
|
486
|
+
clientTxId,
|
|
487
|
+
code: String(error?.code || 'UNKNOWN_ERROR'),
|
|
488
|
+
message: String(error?.message || 'Dynamic transaction failed'),
|
|
489
|
+
})
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
```
|
|
494
|
+
|
|
495
|
+
## Privy Integration (React)
|
|
496
|
+
|
|
497
|
+
### Install
|
|
498
|
+
|
|
499
|
+
```bash
|
|
500
|
+
pnpm add @privy-io/react-auth viem
|
|
501
|
+
# or npm/yarn equivalents
|
|
502
|
+
```
|
|
503
|
+
|
|
504
|
+
### Provider setup
|
|
505
|
+
|
|
506
|
+
```tsx
|
|
507
|
+
'use client'
|
|
508
|
+
|
|
509
|
+
import { PrivyProvider } from '@privy-io/react-auth'
|
|
510
|
+
|
|
511
|
+
export function PrivyProviders({ children }: { children: React.ReactNode }) {
|
|
512
|
+
return (
|
|
513
|
+
<PrivyProvider
|
|
514
|
+
appId={process.env.NEXT_PUBLIC_PRIVY_APP_ID!}
|
|
515
|
+
clientId={process.env.NEXT_PUBLIC_PRIVY_CLIENT_ID!}
|
|
516
|
+
config={{
|
|
517
|
+
embeddedWallets: {
|
|
518
|
+
createOnLogin: 'users-without-wallets',
|
|
519
|
+
},
|
|
520
|
+
}}
|
|
521
|
+
>
|
|
522
|
+
{children}
|
|
523
|
+
</PrivyProvider>
|
|
524
|
+
)
|
|
525
|
+
}
|
|
526
|
+
```
|
|
527
|
+
|
|
528
|
+
### `processBytecode` using Privy connected wallets
|
|
529
|
+
|
|
530
|
+
```tsx
|
|
531
|
+
'use client'
|
|
532
|
+
|
|
533
|
+
import { useWallets } from '@privy-io/react-auth'
|
|
534
|
+
|
|
535
|
+
type Bytecode = { chainId?: number; to: string; data: string; value: string }
|
|
536
|
+
|
|
537
|
+
async function waitForReceipt(
|
|
538
|
+
provider: { request: (args: { method: string; params?: any[] }) => Promise<any> },
|
|
539
|
+
txHash: string
|
|
540
|
+
) {
|
|
541
|
+
for (;;) {
|
|
542
|
+
const receipt = await provider.request({
|
|
543
|
+
method: 'eth_getTransactionReceipt',
|
|
544
|
+
params: [txHash],
|
|
545
|
+
})
|
|
546
|
+
|
|
547
|
+
if (receipt) return receipt
|
|
548
|
+
await new Promise((resolve) => setTimeout(resolve, 1500))
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
export function usePrivyDeframeProcessBytecode() {
|
|
553
|
+
const { wallets, ready } = useWallets()
|
|
554
|
+
|
|
555
|
+
return async (
|
|
556
|
+
payload: { clientTxId: string; bytecodes: Bytecode[] },
|
|
557
|
+
ctx: { updateTxStatus: (event: any) => void }
|
|
558
|
+
) => {
|
|
559
|
+
const { clientTxId, bytecodes } = payload
|
|
560
|
+
|
|
561
|
+
if (!ready || wallets.length === 0) {
|
|
562
|
+
ctx.updateTxStatus({
|
|
563
|
+
type: 'SIGNATURE_ERROR',
|
|
564
|
+
clientTxId,
|
|
565
|
+
code: 'NO_WALLET',
|
|
566
|
+
message: 'No Privy wallet is connected',
|
|
567
|
+
})
|
|
568
|
+
return
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
const wallet = wallets[0]
|
|
572
|
+
|
|
573
|
+
try {
|
|
574
|
+
ctx.updateTxStatus({ type: 'HOST_ACK', clientTxId })
|
|
575
|
+
|
|
576
|
+
for (const tx of bytecodes) {
|
|
577
|
+
if (tx.chainId) {
|
|
578
|
+
await wallet.switchChain(tx.chainId)
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
const provider = await wallet.getEthereumProvider()
|
|
582
|
+
|
|
583
|
+
ctx.updateTxStatus({ type: 'SIGNATURE_PROMPTED', clientTxId })
|
|
584
|
+
|
|
585
|
+
const txHash = await provider.request({
|
|
586
|
+
method: 'eth_sendTransaction',
|
|
587
|
+
params: [
|
|
588
|
+
{
|
|
589
|
+
from: wallet.address,
|
|
590
|
+
to: tx.to,
|
|
591
|
+
data: tx.data,
|
|
592
|
+
value: `0x${BigInt(tx.value || '0').toString(16)}`,
|
|
593
|
+
},
|
|
594
|
+
],
|
|
595
|
+
})
|
|
596
|
+
|
|
597
|
+
ctx.updateTxStatus({
|
|
598
|
+
type: 'TX_SUBMITTED',
|
|
599
|
+
clientTxId,
|
|
600
|
+
chainId: tx.chainId,
|
|
601
|
+
txHash,
|
|
602
|
+
})
|
|
603
|
+
|
|
604
|
+
await waitForReceipt(provider, txHash)
|
|
605
|
+
ctx.updateTxStatus({ type: 'TX_CONFIRMED', clientTxId, txHash })
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
ctx.updateTxStatus({ type: 'TX_FINALIZED', clientTxId })
|
|
609
|
+
} catch (error: any) {
|
|
610
|
+
if (error?.code === 4001 || error?.code === 'ACTION_REJECTED') {
|
|
611
|
+
ctx.updateTxStatus({ type: 'SIGNATURE_DECLINED', clientTxId })
|
|
612
|
+
return
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
ctx.updateTxStatus({
|
|
616
|
+
type: 'SIGNATURE_ERROR',
|
|
617
|
+
clientTxId,
|
|
618
|
+
code: String(error?.code || 'UNKNOWN_ERROR'),
|
|
619
|
+
message: String(error?.message || 'Privy transaction failed'),
|
|
620
|
+
})
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
```
|
|
625
|
+
|
|
626
|
+
## API Reference
|
|
627
|
+
|
|
628
|
+
### `EarnWidget` props
|
|
629
|
+
|
|
630
|
+
```ts
|
|
631
|
+
type EarnWidgetProps = {
|
|
632
|
+
className?: string
|
|
633
|
+
style?: React.CSSProperties
|
|
634
|
+
height?: string | number
|
|
635
|
+
enableScroll?: boolean
|
|
636
|
+
autoHeight?: boolean
|
|
637
|
+
onRouteChange?: (routeName: string) => void
|
|
638
|
+
}
|
|
639
|
+
```
|
|
640
|
+
|
|
641
|
+
### `SwapWidget` props
|
|
642
|
+
|
|
643
|
+
```ts
|
|
644
|
+
type SwapWidgetProps = {
|
|
645
|
+
className?: string
|
|
646
|
+
style?: React.CSSProperties
|
|
647
|
+
height?: string | number
|
|
648
|
+
enableScroll?: boolean
|
|
649
|
+
autoHeight?: boolean
|
|
650
|
+
fromTokenAddress?: string
|
|
651
|
+
fromChainId?: number
|
|
652
|
+
toTokenAddress?: string
|
|
653
|
+
toChainId?: number
|
|
654
|
+
}
|
|
655
|
+
```
|
|
656
|
+
|
|
657
|
+
### `DeframeConfig`
|
|
658
|
+
|
|
659
|
+
```ts
|
|
660
|
+
type DeframeConfig = {
|
|
661
|
+
DEFRAME_API_URL?: string
|
|
662
|
+
DEFRAME_API_KEY?: string
|
|
663
|
+
walletAddress?: string
|
|
664
|
+
userId?: string
|
|
665
|
+
strategiesLimit?: number
|
|
666
|
+
globalCurrency?: 'USD' | 'BRL'
|
|
667
|
+
globalCurrencyExchangeRate?: number
|
|
668
|
+
theme?: {
|
|
669
|
+
mode?: 'light' | 'dark' | 'auto'
|
|
670
|
+
preset?: 'default' | 'cryptocontrol'
|
|
671
|
+
overrides?: {
|
|
672
|
+
light?: { colors?: Record<string, string> }
|
|
673
|
+
dark?: { colors?: Record<string, string> }
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
debug?: boolean
|
|
677
|
+
components?: ComponentOverridesMap
|
|
678
|
+
behavior?: {
|
|
679
|
+
swap?: {
|
|
680
|
+
initialChainStrategy?: 'fixed' | 'wallet-balance'
|
|
681
|
+
openProcessingHistoryInline?: boolean
|
|
682
|
+
showHistoryTooltip?: boolean
|
|
683
|
+
directionButtonSpacing?: 'default' | 'compact'
|
|
684
|
+
}
|
|
685
|
+
actionSheets?: {
|
|
686
|
+
closeOnBackdropClick?: boolean
|
|
687
|
+
focusSearchOnOpen?: boolean
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
```
|
|
692
|
+
|
|
693
|
+
### Behavior Configuration
|
|
694
|
+
|
|
695
|
+
`config.behavior` lets host wallets opt into wallet-specific UI behavior without changing the SDK defaults for every consumer. Omit this config to keep the shared behavior.
|
|
696
|
+
|
|
697
|
+
```tsx
|
|
698
|
+
const config = {
|
|
699
|
+
...baseConfig,
|
|
700
|
+
behavior: {
|
|
701
|
+
swap: {
|
|
702
|
+
initialChainStrategy: 'wallet-balance',
|
|
703
|
+
openProcessingHistoryInline: true,
|
|
704
|
+
showHistoryTooltip: true,
|
|
705
|
+
directionButtonSpacing: 'compact',
|
|
706
|
+
},
|
|
707
|
+
actionSheets: {
|
|
708
|
+
closeOnBackdropClick: true,
|
|
709
|
+
focusSearchOnOpen: true,
|
|
710
|
+
},
|
|
711
|
+
},
|
|
712
|
+
}
|
|
713
|
+
```
|
|
714
|
+
|
|
715
|
+
- `swap.initialChainStrategy`: defaults to `fixed`; use `wallet-balance` to start swap on the visible chain with the highest wallet balance.
|
|
716
|
+
- `swap.openProcessingHistoryInline`: defaults to `false`; set `true` to keep processing-screen history navigation inside the swap flow.
|
|
717
|
+
- `swap.showHistoryTooltip`: defaults to `false`; set `true` to expose the swap history icon label/tooltip.
|
|
718
|
+
- `swap.directionButtonSpacing`: defaults to `default`; use `compact` to reduce the vertical overlap around the simple swap direction button.
|
|
719
|
+
- `actionSheets.closeOnBackdropClick`: defaults to `false`; set `true` to close token/network selectors when the backdrop is clicked.
|
|
720
|
+
- `actionSheets.focusSearchOnOpen`: defaults to `false`; set `true` to focus selector search inputs when they open.
|
|
721
|
+
|
|
722
|
+
## Component Overrides
|
|
723
|
+
|
|
724
|
+
Hosts can replace specific SDK view components via `config.components`, without forking. For example:
|
|
725
|
+
|
|
726
|
+
```tsx
|
|
727
|
+
import { ChooseAnAssetSwapViewCardGrid } from 'deframe-sdk'
|
|
728
|
+
|
|
729
|
+
const config = {
|
|
730
|
+
...baseConfig,
|
|
731
|
+
components: {
|
|
732
|
+
ChooseAnAssetSwapView: ChooseAnAssetSwapViewCardGrid
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
```
|
|
736
|
+
|
|
737
|
+
If no override is set, the default component is used.
|
|
738
|
+
|
|
739
|
+
## Troubleshooting
|
|
740
|
+
|
|
741
|
+
- Widget renders with no data:
|
|
742
|
+
- Verify `DEFRAME_API_URL`, `DEFRAME_API_KEY`, and `walletAddress`.
|
|
743
|
+
- Tx flow stuck in processing:
|
|
744
|
+
- Ensure host emits `TX_SUBMITTED`, then `TX_CONFIRMED`, then `TX_FINALIZED`.
|
|
745
|
+
- Signature rejected path not handled:
|
|
746
|
+
- Map wallet rejection errors (`4001` / `ACTION_REJECTED`) to `SIGNATURE_DECLINED`.
|
|
747
|
+
- Cross-route actions should be handled through `onRouteChange`.
|
|
748
|
+
- Widget appears with unexpected light cards/surfaces in dark mode:
|
|
749
|
+
- Inspect `.deframe-widget` computed variables and verify:
|
|
750
|
+
- `--color-bg-default`
|
|
751
|
+
- `--color-bg-raised`
|
|
752
|
+
- `--color-text-primary`
|
|
753
|
+
- If `--color-bg-raised` resolves to a light value while using dark theme, set widget-scoped fallbacks:
|
|
754
|
+
- `--color-bg-raised: var(--deframe-bg-raised, #232323)`
|
|
755
|
+
- `--color-brand-tint: #1e1e3f`
|
|
756
|
+
- Keep these overrides scoped to `.deframe-widget`, never global.
|
|
757
|
+
|
|
758
|
+
## Machine Companion
|
|
759
|
+
|
|
760
|
+
For AI/editor ingestion, use [llms-full.txt](./llms-full.txt).
|