@shapeshiftoss/swap-widget 0.0.2 → 0.1.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 (159) hide show
  1. package/dist/index.d.ts +233 -0
  2. package/dist/index.js +63612 -0
  3. package/dist/style.css +1 -0
  4. package/package.json +69 -18
  5. package/Dockerfile +0 -87
  6. package/dist/assets/PhArrowCircleDown-B305t-Sh.js +0 -14
  7. package/dist/assets/PhArrowClockwise-CJPxQhr_.js +0 -14
  8. package/dist/assets/PhArrowDown-C4hT9BVu.js +0 -14
  9. package/dist/assets/PhArrowLeft-Way4Cu-r.js +0 -14
  10. package/dist/assets/PhArrowRight-Cp5ZME0F.js +0 -14
  11. package/dist/assets/PhArrowSquareOut-NnrK69c5.js +0 -14
  12. package/dist/assets/PhArrowUp-Dph6j8rm.js +0 -14
  13. package/dist/assets/PhArrowUpRight-BpJjRRRh.js +0 -14
  14. package/dist/assets/PhArrowsClockwise-CFUT8X7R.js +0 -14
  15. package/dist/assets/PhArrowsDownUp-BjBI4ckC.js +0 -14
  16. package/dist/assets/PhArrowsLeftRight-CuLpbKRk.js +0 -14
  17. package/dist/assets/PhBank-Dchr4XQJ.js +0 -14
  18. package/dist/assets/PhBrowser-dUu2TrC1.js +0 -14
  19. package/dist/assets/PhCaretDown-78IuKU3V.js +0 -14
  20. package/dist/assets/PhCaretLeft-_aiyH7n1.js +0 -14
  21. package/dist/assets/PhCaretRight-8zJQEuDX.js +0 -14
  22. package/dist/assets/PhCaretUp-CiCxKWwN.js +0 -14
  23. package/dist/assets/PhCheck-CcADx8br.js +0 -14
  24. package/dist/assets/PhCircleHalf-BYzSzd2h.js +0 -14
  25. package/dist/assets/PhClock-UItiXeJq.js +0 -14
  26. package/dist/assets/PhCompass-CUy3uA7t.js +0 -14
  27. package/dist/assets/PhCopy-C-PDgSlZ.js +0 -14
  28. package/dist/assets/PhCreditCard-CWRaUT6F.js +0 -14
  29. package/dist/assets/PhCurrencyDollar-Cqla3AXT.js +0 -14
  30. package/dist/assets/PhDesktop-BBIPrYLl.js +0 -14
  31. package/dist/assets/PhDeviceMobile-BdsPaATg.js +0 -14
  32. package/dist/assets/PhDotsThree-BMXCQl-0.js +0 -14
  33. package/dist/assets/PhEnvelope-yUsis6yU.js +0 -14
  34. package/dist/assets/PhFunnelSimple-Ba7BbWTp.js +0 -14
  35. package/dist/assets/PhGlobe-DgLxBk5U.js +0 -14
  36. package/dist/assets/PhIdentificationCard-Czjmq9Z3.js +0 -14
  37. package/dist/assets/PhImage-BAJ_erz6.js +0 -14
  38. package/dist/assets/PhInfo-Cr4DhVUE.js +0 -14
  39. package/dist/assets/PhLightbulb-BX_7duTr.js +0 -14
  40. package/dist/assets/PhMagnifyingGlass-Mygfryvz.js +0 -14
  41. package/dist/assets/PhPaperPlaneRight-BeuCA660.js +0 -14
  42. package/dist/assets/PhPlus-BMjcHjsT.js +0 -14
  43. package/dist/assets/PhPower-CGffGmdb.js +0 -14
  44. package/dist/assets/PhPuzzlePiece-wm_GpVSi.js +0 -14
  45. package/dist/assets/PhQrCode-DRwRzXCH.js +0 -14
  46. package/dist/assets/PhQuestion-M09j2U0T.js +0 -14
  47. package/dist/assets/PhQuestionMark-BP9EMB6h.js +0 -14
  48. package/dist/assets/PhSealCheck-BfG80yKn.js +0 -14
  49. package/dist/assets/PhSignOut-C5YOWlPT.js +0 -14
  50. package/dist/assets/PhSpinner-BXooDYzU.js +0 -14
  51. package/dist/assets/PhTrash-Biq6rmmL.js +0 -14
  52. package/dist/assets/PhUser-CAgZSpGe.js +0 -14
  53. package/dist/assets/PhVault-l2PHF38a.js +0 -14
  54. package/dist/assets/PhWallet-w25D16It.js +0 -14
  55. package/dist/assets/PhWarning-DPEydIPw.js +0 -14
  56. package/dist/assets/PhWarningCircle-BqjT745H.js +0 -14
  57. package/dist/assets/PhX-s-SmVExa.js +0 -14
  58. package/dist/assets/SwapController-If0bFrNc.js +0 -1
  59. package/dist/assets/ccip-BBB7uCdL.js +0 -1
  60. package/dist/assets/ccip-CkkdfKKI.js +0 -1
  61. package/dist/assets/data-capture-D4gAy-Yc.js +0 -242
  62. package/dist/assets/email-B1AJehis.js +0 -90
  63. package/dist/assets/embedded-wallet-Q6DQopDk.js +0 -410
  64. package/dist/assets/features-B6JAPAFb.js +0 -5
  65. package/dist/assets/index-5jd8RPN9.js +0 -7428
  66. package/dist/assets/index-B4kNtSTk.js +0 -1080
  67. package/dist/assets/index-B753eAob.js +0 -1
  68. package/dist/assets/index-BZoLTv77.js +0 -3
  69. package/dist/assets/index-Bcw9UURX.js +0 -3
  70. package/dist/assets/index-BkrV-ahK.js +0 -2
  71. package/dist/assets/index-CRQzQ_up.js +0 -9
  72. package/dist/assets/index-CSW0Gt5y.js +0 -132
  73. package/dist/assets/index-CZ4jTIsk.js +0 -138
  74. package/dist/assets/index-Cwa8SB3h.js +0 -61
  75. package/dist/assets/index-DEwQgT4r.js +0 -78
  76. package/dist/assets/index-DVfQiQ1d.js +0 -1
  77. package/dist/assets/index-cV3UdaMs.css +0 -1
  78. package/dist/assets/index-hAmu622O.js +0 -43
  79. package/dist/assets/onramp-XcPNCLRU.js +0 -422
  80. package/dist/assets/pay-with-exchange-BeHt4OF4.js +0 -280
  81. package/dist/assets/property-C9JG5tag.js +0 -27
  82. package/dist/assets/receive-7ff4he2S.js +0 -131
  83. package/dist/assets/send-CkMBIRXT.js +0 -554
  84. package/dist/assets/socials-DmmxuLrP.js +0 -250
  85. package/dist/assets/swaps-IHAYRQ0x.js +0 -1050
  86. package/dist/assets/transactions-9Cxdk7o9.js +0 -16
  87. package/dist/assets/v4-BOvFkHkt.js +0 -1
  88. package/dist/assets/w3m-modal-kJzFnBfB.js +0 -891
  89. package/dist/assets/wallet-standard-Dv8LMoUB.js +0 -1
  90. package/dist/favicon.png +0 -0
  91. package/dist/favicon.svg +0 -11
  92. package/dist/icon-192x192.png +0 -0
  93. package/dist/icon-512x512.png +0 -0
  94. package/dist/index.html +0 -33
  95. package/index.html +0 -32
  96. package/public/favicon.png +0 -0
  97. package/public/favicon.svg +0 -11
  98. package/public/icon-192x192.png +0 -0
  99. package/public/icon-512x512.png +0 -0
  100. package/railway.toml +0 -10
  101. package/src/api/client.ts +0 -95
  102. package/src/components/AddressInputModal.css +0 -173
  103. package/src/components/AddressInputModal.tsx +0 -250
  104. package/src/components/ApprovalStep.tsx +0 -92
  105. package/src/components/ExecutionStep.tsx +0 -27
  106. package/src/components/InputStep.tsx +0 -431
  107. package/src/components/QuoteSelector.css +0 -146
  108. package/src/components/QuoteSelector.tsx +0 -137
  109. package/src/components/QuotesModal.css +0 -250
  110. package/src/components/QuotesModal.tsx +0 -182
  111. package/src/components/SettingsModal.css +0 -145
  112. package/src/components/SettingsModal.tsx +0 -180
  113. package/src/components/StatusStep.tsx +0 -139
  114. package/src/components/SwapWidget.css +0 -713
  115. package/src/components/SwapWidget.tsx +0 -607
  116. package/src/components/TokenSelectModal.css +0 -438
  117. package/src/components/TokenSelectModal.tsx +0 -487
  118. package/src/components/WalletProvider.tsx +0 -92
  119. package/src/config/appkit.ts +0 -104
  120. package/src/config/wagmi.ts +0 -27
  121. package/src/constants/chains.ts +0 -72
  122. package/src/constants/defaults.ts +0 -28
  123. package/src/constants/swappers.ts +0 -48
  124. package/src/constants/viemChains.ts +0 -69
  125. package/src/contexts/SwapWalletContext.tsx +0 -25
  126. package/src/demo/App.css +0 -458
  127. package/src/demo/App.tsx +0 -481
  128. package/src/demo/main.tsx +0 -25
  129. package/src/hooks/useAssets.ts +0 -180
  130. package/src/hooks/useBalances.ts +0 -822
  131. package/src/hooks/useBitcoinSigning.ts +0 -276
  132. package/src/hooks/useMarketData.ts +0 -169
  133. package/src/hooks/useSolanaSigning.ts +0 -275
  134. package/src/hooks/useStatusPolling.ts +0 -137
  135. package/src/hooks/useSwapApproval.ts +0 -106
  136. package/src/hooks/useSwapDisplayValues.ts +0 -157
  137. package/src/hooks/useSwapExecution.ts +0 -199
  138. package/src/hooks/useSwapHandlers.ts +0 -119
  139. package/src/hooks/useSwapQuote.ts +0 -71
  140. package/src/hooks/useSwapQuoting.ts +0 -102
  141. package/src/hooks/useSwapRates.ts +0 -61
  142. package/src/index.ts +0 -43
  143. package/src/machines/SwapMachineContext.ts +0 -5
  144. package/src/machines/__tests__/guards.test.ts +0 -228
  145. package/src/machines/__tests__/setup.test.ts +0 -7
  146. package/src/machines/__tests__/swapMachine.test.ts +0 -544
  147. package/src/machines/__tests__/types.test.ts +0 -124
  148. package/src/machines/guards.ts +0 -33
  149. package/src/machines/swapMachine.ts +0 -288
  150. package/src/machines/types.ts +0 -54
  151. package/src/services/transactionStatus.ts +0 -322
  152. package/src/types/index.ts +0 -361
  153. package/src/utils/addressValidation.ts +0 -201
  154. package/src/utils/redirect.ts +0 -45
  155. package/src/vite-env.d.ts +0 -10
  156. package/tsconfig.json +0 -23
  157. package/tsconfig.node.json +0 -10
  158. package/vite.config.ts +0 -101
  159. package/vitest.config.ts +0 -18
package/src/demo/App.tsx DELETED
@@ -1,481 +0,0 @@
1
- import './App.css'
2
-
3
- import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
4
- import { useCallback, useMemo, useState } from 'react'
5
-
6
- import { SwapWidget } from '../components/SwapWidget'
7
- import type { ThemeConfig } from '../types'
8
-
9
- const PROJECT_ID = 'f58c0242def84c3b9befe9b1e6086bbd'
10
-
11
- const queryClient = new QueryClient()
12
-
13
- type ThemeColors = {
14
- bg: string
15
- card: string
16
- accent: string
17
- borderColor?: string
18
- borderRadius?: string
19
- buttonVariant?: 'filled' | 'outline'
20
- }
21
-
22
- const THEME_PRESETS: {
23
- name: string
24
- dark: ThemeColors
25
- light: ThemeColors
26
- }[] = [
27
- {
28
- name: 'Blue',
29
- dark: { bg: '#0a0a14', card: '#12121c', accent: '#3861fb' },
30
- light: { bg: '#f8f9fc', card: '#ffffff', accent: '#3861fb' },
31
- },
32
- {
33
- name: 'Rose',
34
- dark: { bg: '#140a0f', card: '#1c1218', accent: '#f43f5e' },
35
- light: { bg: '#fef2f4', card: '#ffffff', accent: '#f43f5e' },
36
- },
37
- {
38
- name: 'Purple',
39
- dark: { bg: '#0e0a14', card: '#1a1424', accent: '#a855f7' },
40
- light: { bg: '#faf5ff', card: '#ffffff', accent: '#a855f7' },
41
- },
42
- {
43
- name: 'Cyan',
44
- dark: { bg: '#0a1214', card: '#141d20', accent: '#06b6d4' },
45
- light: { bg: '#f0fdff', card: '#ffffff', accent: '#06b6d4' },
46
- },
47
- {
48
- name: 'Green',
49
- dark: { bg: '#0a140e', card: '#141c18', accent: '#10b981' },
50
- light: { bg: '#f0fdf6', card: '#ffffff', accent: '#10b981' },
51
- },
52
- {
53
- name: 'Orange',
54
- dark: { bg: '#14100a', card: '#1c1814', accent: '#f97316' },
55
- light: { bg: '#fff8f3', card: '#ffffff', accent: '#f97316' },
56
- },
57
- {
58
- name: 'Stucco',
59
- dark: {
60
- bg: '#0d1117',
61
- card: '#0d1117',
62
- accent: '#bea989',
63
- borderColor: '#2a2520',
64
- borderRadius: '6',
65
- buttonVariant: 'outline' as const,
66
- },
67
- light: {
68
- bg: '#f5f3ee',
69
- card: '#f5f3ee',
70
- accent: '#b8941f',
71
- borderColor: '#d4cfc7',
72
- borderRadius: '6',
73
- buttonVariant: 'outline' as const,
74
- },
75
- },
76
- ]
77
-
78
- type DemoContentProps = {
79
- theme: 'light' | 'dark'
80
- setTheme: (theme: 'light' | 'dark') => void
81
- }
82
-
83
- const DemoContent = ({ theme, setTheme }: DemoContentProps) => {
84
- const [showCustomizer, setShowCustomizer] = useState(true)
85
-
86
- const [darkColors, setDarkColors] = useState<ThemeColors>({
87
- bg: '#0a0a14',
88
- card: '#12121c',
89
- accent: '#3861fb',
90
- })
91
-
92
- const [lightColors, setLightColors] = useState<ThemeColors>({
93
- bg: '#f8f9fc',
94
- card: '#ffffff',
95
- accent: '#3861fb',
96
- })
97
-
98
- const currentColors = theme === 'dark' ? darkColors : lightColors
99
- const setCurrentColors = theme === 'dark' ? setDarkColors : setLightColors
100
-
101
- const themeConfig: ThemeConfig = useMemo(
102
- () => ({
103
- mode: theme,
104
- accentColor: currentColors.accent,
105
- backgroundColor: currentColors.bg,
106
- cardColor: currentColors.card,
107
- borderColor: currentColors.borderColor,
108
- borderRadius: currentColors.borderRadius,
109
- buttonVariant: currentColors.buttonVariant,
110
- }),
111
- [theme, currentColors],
112
- )
113
-
114
- const applyPreset = (preset: (typeof THEME_PRESETS)[0]) => {
115
- setDarkColors(preset.dark)
116
- setLightColors(preset.light)
117
- }
118
-
119
- const [copied, setCopied] = useState(false)
120
-
121
- const copyConfig = useCallback(() => {
122
- const formatColors = (colors: ThemeColors, mode: string) => {
123
- const lines = [
124
- ` mode: "${mode}",`,
125
- ` backgroundColor: "${colors.bg}",`,
126
- ` cardColor: "${colors.card}",`,
127
- ` accentColor: "${colors.accent}",`,
128
- ]
129
- if (colors.borderColor) lines.push(` borderColor: "${colors.borderColor}",`)
130
- if (colors.borderRadius) lines.push(` borderRadius: "${colors.borderRadius}",`)
131
- if (colors.buttonVariant) lines.push(` buttonVariant: "${colors.buttonVariant}",`)
132
- return lines.join('\n')
133
- }
134
-
135
- const code = `const themeConfig = {
136
- dark: {
137
- ${formatColors(darkColors, 'dark')}
138
- },
139
- light: {
140
- ${formatColors(lightColors, 'light')}
141
- },
142
- };
143
-
144
- // Usage:
145
- <SwapWidget theme={themeConfig.dark} />
146
- // or
147
- <SwapWidget theme={themeConfig.light} />`
148
-
149
- navigator.clipboard.writeText(code).then(() => {
150
- setCopied(true)
151
- setTimeout(() => setCopied(false), 2000)
152
- })
153
- }, [darkColors, lightColors])
154
-
155
- const handleSwapSuccess = (txHash: string) => {
156
- console.log('Swap successful:', txHash)
157
- }
158
-
159
- const handleSwapError = (error: Error) => {
160
- console.error('Swap failed:', error)
161
- }
162
-
163
- const demoStyle = useMemo(
164
- () =>
165
- ({
166
- '--demo-page-bg': currentColors.bg,
167
- '--demo-page-accent': currentColors.accent,
168
- }) as React.CSSProperties,
169
- [currentColors],
170
- )
171
-
172
- return (
173
- <div className={`demo-app ${theme}`} style={demoStyle}>
174
- <header className='demo-header'>
175
- <a
176
- href='https://shapeshift.com'
177
- className='demo-logo'
178
- target='_blank'
179
- rel='noopener noreferrer'
180
- >
181
- <svg width='28' height='28' viewBox='0 0 57 62' fill='currentColor'>
182
- <path d='M51.67 5.1L48.97 21.3L39.37 10L51.67 5.1ZM49.03 28.27L51.43 37.14L33.06 42.2L49.03 28.27ZM9.03 23.8L18.88 10.93H35.99L46.92 23.8H9.03ZM45.66 26.99L27.85 42.53L9.7 26.99H45.66ZM15.58 10.01L6.78 21.51L4.08 5.17L15.58 10.01ZM22.57 42.2L4.02 37.15L6.56 28.48L22.57 42.2ZM25.99 46.43L22.49 50.28C19.53 47.46 16.26 44.96 12.78 42.83L25.99 46.43ZM42.98 42.77C39.5 44.94 36.24 47.47 33.29 50.32L29.72 46.42L42.98 42.77ZM55.73 0.06L36.42 7.75H18.42L0 0L4.18 25.3L0.17 38.99L10.65 45.26C15.61 48.23 20.06 51.94 23.86 56.3L27.94 60.97L32.23 56.06C35.9 51.84 40.18 48.22 44.95 45.29L55.23 38.99L51.52 25.31L55.73 0.06Z' />
183
- </svg>
184
- <span className='demo-logo-text'>ShapeShift</span>
185
- </a>
186
-
187
- <div className='demo-header-actions'>
188
- <button
189
- className='demo-customize-btn'
190
- onClick={() => setShowCustomizer(!showCustomizer)}
191
- type='button'
192
- >
193
- <svg
194
- width='18'
195
- height='18'
196
- viewBox='0 0 24 24'
197
- fill='none'
198
- stroke='currentColor'
199
- strokeWidth='2'
200
- >
201
- <circle cx='12' cy='12' r='3' />
202
- <path d='M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z' />
203
- </svg>
204
- Customize
205
- </button>
206
- </div>
207
- </header>
208
-
209
- <main className='demo-main'>
210
- <div className='demo-content'>
211
- <div className='demo-hero'>
212
- <h1 className='demo-title'>Swap Widget</h1>
213
- <p className='demo-subtitle'>
214
- Embeddable multi-chain swap widget powered by ShapeShift
215
- </p>
216
- </div>
217
-
218
- <div className='demo-layout'>
219
- {showCustomizer && (
220
- <div className='demo-customizer'>
221
- <h3 className='demo-customizer-title'>Customize Widget</h3>
222
-
223
- <div className='demo-customizer-section'>
224
- <span className='demo-customizer-label'>Presets</span>
225
- <div className='demo-preset-grid'>
226
- {THEME_PRESETS.map(preset => {
227
- const previewColors = theme === 'dark' ? preset.dark : preset.light
228
- return (
229
- <button
230
- key={preset.name}
231
- className='demo-preset-btn'
232
- onClick={() => applyPreset(preset)}
233
- title={preset.name}
234
- type='button'
235
- >
236
- <div
237
- className='demo-preset-preview'
238
- style={{ background: previewColors.bg }}
239
- >
240
- <div
241
- className='demo-preset-card'
242
- style={{ background: previewColors.card }}
243
- />
244
- <div
245
- className='demo-preset-accent'
246
- style={{ background: previewColors.accent }}
247
- />
248
- </div>
249
- <span className='demo-preset-name'>{preset.name}</span>
250
- </button>
251
- )
252
- })}
253
- </div>
254
- </div>
255
-
256
- <div className='demo-customizer-section'>
257
- <span className='demo-customizer-label'>Theme</span>
258
- <div className='demo-theme-toggle'>
259
- <button
260
- className={`demo-theme-btn ${theme === 'light' ? 'active' : ''}`}
261
- onClick={() => setTheme('light')}
262
- type='button'
263
- >
264
- <svg
265
- width='16'
266
- height='16'
267
- viewBox='0 0 24 24'
268
- fill='none'
269
- stroke='currentColor'
270
- strokeWidth='2'
271
- >
272
- <circle cx='12' cy='12' r='5' />
273
- <path d='M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42' />
274
- </svg>
275
- Light
276
- </button>
277
- <button
278
- className={`demo-theme-btn ${theme === 'dark' ? 'active' : ''}`}
279
- onClick={() => setTheme('dark')}
280
- type='button'
281
- >
282
- <svg
283
- width='16'
284
- height='16'
285
- viewBox='0 0 24 24'
286
- fill='none'
287
- stroke='currentColor'
288
- strokeWidth='2'
289
- >
290
- <path d='M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z' />
291
- </svg>
292
- Dark
293
- </button>
294
- </div>
295
- </div>
296
-
297
- <div className='demo-customizer-section'>
298
- <span className='demo-customizer-label'>Background Color</span>
299
- <div className='demo-color-input-row'>
300
- <input
301
- type='color'
302
- value={currentColors.bg}
303
- onChange={e => setCurrentColors(c => ({ ...c, bg: e.target.value }))}
304
- className='demo-color-picker'
305
- />
306
- <input
307
- type='text'
308
- value={currentColors.bg}
309
- onChange={e => setCurrentColors(c => ({ ...c, bg: e.target.value }))}
310
- className='demo-color-text'
311
- />
312
- </div>
313
- </div>
314
-
315
- <div className='demo-customizer-section'>
316
- <span className='demo-customizer-label'>Card Color</span>
317
- <div className='demo-color-input-row'>
318
- <input
319
- type='color'
320
- value={currentColors.card}
321
- onChange={e =>
322
- setCurrentColors(c => ({
323
- ...c,
324
- card: e.target.value,
325
- }))
326
- }
327
- className='demo-color-picker'
328
- />
329
- <input
330
- type='text'
331
- value={currentColors.card}
332
- onChange={e =>
333
- setCurrentColors(c => ({
334
- ...c,
335
- card: e.target.value,
336
- }))
337
- }
338
- className='demo-color-text'
339
- />
340
- </div>
341
- </div>
342
-
343
- <div className='demo-customizer-section'>
344
- <span className='demo-customizer-label'>Accent Color</span>
345
- <div className='demo-color-input-row'>
346
- <input
347
- type='color'
348
- value={currentColors.accent}
349
- onChange={e =>
350
- setCurrentColors(c => ({
351
- ...c,
352
- accent: e.target.value,
353
- }))
354
- }
355
- className='demo-color-picker'
356
- />
357
- <input
358
- type='text'
359
- value={currentColors.accent}
360
- onChange={e =>
361
- setCurrentColors(c => ({
362
- ...c,
363
- accent: e.target.value,
364
- }))
365
- }
366
- className='demo-color-text'
367
- />
368
- </div>
369
- </div>
370
-
371
- <div className='demo-customizer-section'>
372
- <span className='demo-customizer-label'>Border Radius</span>
373
- <div className='demo-color-input-row'>
374
- <input
375
- type='range'
376
- min='0'
377
- max='20'
378
- value={currentColors.borderRadius ?? '16'}
379
- onChange={e =>
380
- setCurrentColors(c => ({ ...c, borderRadius: e.target.value }))
381
- }
382
- className='demo-range-input'
383
- />
384
- <input
385
- type='text'
386
- value={`${currentColors.borderRadius ?? '16'}px`}
387
- readOnly
388
- className='demo-color-text'
389
- style={{ width: 60 }}
390
- />
391
- </div>
392
- </div>
393
-
394
- <div className='demo-customizer-section'>
395
- <span className='demo-customizer-label'>Button Style</span>
396
- <div className='demo-theme-toggle'>
397
- <button
398
- className={`demo-theme-btn ${
399
- currentColors.buttonVariant !== 'outline' ? 'active' : ''
400
- }`}
401
- onClick={() => setCurrentColors(c => ({ ...c, buttonVariant: 'filled' }))}
402
- type='button'
403
- >
404
- Filled
405
- </button>
406
- <button
407
- className={`demo-theme-btn ${
408
- currentColors.buttonVariant === 'outline' ? 'active' : ''
409
- }`}
410
- onClick={() => setCurrentColors(c => ({ ...c, buttonVariant: 'outline' }))}
411
- type='button'
412
- >
413
- Outline
414
- </button>
415
- </div>
416
- </div>
417
-
418
- <div className='demo-customizer-section'>
419
- <button className='demo-copy-btn' onClick={copyConfig} type='button'>
420
- {copied ? (
421
- <>
422
- <svg
423
- width='16'
424
- height='16'
425
- viewBox='0 0 24 24'
426
- fill='none'
427
- stroke='currentColor'
428
- strokeWidth='2'
429
- >
430
- <path d='M20 6L9 17l-5-5' />
431
- </svg>
432
- Copied!
433
- </>
434
- ) : (
435
- <>
436
- <svg
437
- width='16'
438
- height='16'
439
- viewBox='0 0 24 24'
440
- fill='none'
441
- stroke='currentColor'
442
- strokeWidth='2'
443
- >
444
- <rect x='9' y='9' width='13' height='13' rx='2' ry='2' />
445
- <path d='M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1' />
446
- </svg>
447
- Copy Theme Config
448
- </>
449
- )}
450
- </button>
451
- </div>
452
- </div>
453
- )}
454
-
455
- <div className='demo-widget-container'>
456
- <SwapWidget
457
- affiliateAddress='0x0000000000000000000000000000000000000001'
458
- theme={themeConfig}
459
- onSwapSuccess={handleSwapSuccess}
460
- onSwapError={handleSwapError}
461
- showPoweredBy={true}
462
- enableWalletConnection={true}
463
- walletConnectProjectId={PROJECT_ID}
464
- />
465
- </div>
466
- </div>
467
- </div>
468
- </main>
469
- </div>
470
- )
471
- }
472
-
473
- export const App = () => {
474
- const [theme, setTheme] = useState<'light' | 'dark'>('dark')
475
-
476
- return (
477
- <QueryClientProvider client={queryClient}>
478
- <DemoContent theme={theme} setTheme={setTheme} />
479
- </QueryClientProvider>
480
- )
481
- }
package/src/demo/main.tsx DELETED
@@ -1,25 +0,0 @@
1
- import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
2
- import React from 'react'
3
- import ReactDOM from 'react-dom/client'
4
-
5
- import { App } from './App'
6
-
7
- const queryClient = new QueryClient({
8
- defaultOptions: {
9
- queries: {
10
- staleTime: 30_000,
11
- refetchOnWindowFocus: false,
12
- },
13
- },
14
- })
15
-
16
- const rootElement = document.getElementById('root')
17
- if (!rootElement) throw new Error('Root element not found')
18
-
19
- ReactDOM.createRoot(rootElement).render(
20
- <React.StrictMode>
21
- <QueryClientProvider client={queryClient}>
22
- <App />
23
- </QueryClientProvider>
24
- </React.StrictMode>,
25
- )
@@ -1,180 +0,0 @@
1
- import { ASSET_NAMESPACE, fromAssetId } from '@shapeshiftoss/caip'
2
- import { useQuery } from '@tanstack/react-query'
3
-
4
- import type { Asset, AssetId, ChainId } from '../types'
5
-
6
- const SHAPESHIFT_ASSET_CDN = 'https://app.shapeshift.com'
7
- const ASSET_QUERY_STALE_TIME = 5 * 60 * 1000
8
-
9
- type AssetManifest = {
10
- assetData: string
11
- relatedAssetIndex: string
12
- }
13
-
14
- type RawAssetData = {
15
- byId: Record<AssetId, Asset>
16
- ids: AssetId[]
17
- }
18
-
19
- const fetchAssetManifest = async (): Promise<AssetManifest> => {
20
- const response = await fetch(`${SHAPESHIFT_ASSET_CDN}/generated/asset-manifest.json`)
21
- if (!response.ok) {
22
- return { assetData: Date.now().toString(), relatedAssetIndex: '' }
23
- }
24
- return response.json()
25
- }
26
-
27
- const fetchAssetData = async (): Promise<RawAssetData> => {
28
- const manifest = await fetchAssetManifest()
29
- const response = await fetch(
30
- `${SHAPESHIFT_ASSET_CDN}/generated/generatedAssetData.json?v=${manifest.assetData}`,
31
- )
32
-
33
- if (!response.ok) {
34
- throw new Error('Failed to fetch asset data')
35
- }
36
-
37
- return response.json()
38
- }
39
-
40
- export const useAssetData = () => {
41
- return useQuery({
42
- queryKey: ['assetData'],
43
- queryFn: fetchAssetData,
44
- staleTime: ASSET_QUERY_STALE_TIME,
45
- gcTime: 30 * 60 * 1000,
46
- })
47
- }
48
-
49
- export const useAssets = () => {
50
- const { data, ...rest } = useAssetData()
51
-
52
- const assets = data ? data.ids.map(id => data.byId[id]).filter(Boolean) : []
53
-
54
- return { data: assets, ...rest }
55
- }
56
-
57
- export const useAssetsById = () => {
58
- const { data, ...rest } = useAssetData()
59
- return { data: data?.byId ?? {}, ...rest }
60
- }
61
-
62
- export const useAssetById = (assetId: AssetId | undefined) => {
63
- const { data: assetsById, ...rest } = useAssetsById()
64
- return {
65
- data: assetId ? assetsById[assetId] : undefined,
66
- ...rest,
67
- }
68
- }
69
-
70
- export type ChainInfo = {
71
- chainId: ChainId
72
- name: string
73
- icon?: string
74
- color?: string
75
- nativeAsset: Asset
76
- }
77
-
78
- const isNativeAsset = (assetId: string): boolean => {
79
- try {
80
- const { assetNamespace } = fromAssetId(assetId)
81
- return assetNamespace === ASSET_NAMESPACE.slip44
82
- } catch {
83
- return false
84
- }
85
- }
86
-
87
- export const useChains = () => {
88
- const { data: assets, ...rest } = useAssets()
89
-
90
- const chains = (() => {
91
- if (!assets.length) return []
92
-
93
- const chainMap = new Map<ChainId, ChainInfo>()
94
-
95
- for (const asset of assets) {
96
- if (chainMap.has(asset.chainId)) continue
97
-
98
- if (isNativeAsset(asset.assetId)) {
99
- chainMap.set(asset.chainId, {
100
- chainId: asset.chainId,
101
- name: asset.networkName ?? asset.name,
102
- icon: (asset as Asset & { networkIcon?: string }).networkIcon ?? asset.icon,
103
- color: (asset as Asset & { networkColor?: string }).networkColor ?? asset.color,
104
- nativeAsset: asset,
105
- })
106
- }
107
- }
108
-
109
- return Array.from(chainMap.values()).sort((a, b) => a.name.localeCompare(b.name))
110
- })()
111
-
112
- return { data: chains, ...rest }
113
- }
114
-
115
- export const useChainInfo = (chainId: ChainId | undefined) => {
116
- const { data: chains, ...rest } = useChains()
117
- const chainInfo = chainId ? chains.find(c => c.chainId === chainId) : undefined
118
- return { data: chainInfo, ...rest }
119
- }
120
-
121
- export const useAssetsByChainId = (chainId: ChainId | undefined) => {
122
- const { data: assets, ...rest } = useAssets()
123
-
124
- const filteredAssets = chainId ? assets.filter(asset => asset.chainId === chainId) : assets
125
-
126
- return { data: filteredAssets, ...rest }
127
- }
128
-
129
- const scoreAsset = (asset: Asset, query: string): number => {
130
- const lowerQuery = query.toLowerCase()
131
- const symbolLower = asset.symbol.toLowerCase()
132
- const nameLower = asset.name.toLowerCase()
133
-
134
- let score = 0
135
-
136
- if (symbolLower === lowerQuery) score += 1000
137
- else if (symbolLower.startsWith(lowerQuery)) score += 500
138
- else if (symbolLower.includes(lowerQuery)) score += 100
139
-
140
- if (nameLower === lowerQuery) score += 800
141
- else if (nameLower.startsWith(lowerQuery)) score += 300
142
- else if (nameLower.includes(lowerQuery)) score += 50
143
-
144
- if (isNativeAsset(asset.assetId)) score += 200
145
-
146
- return score
147
- }
148
-
149
- export const useAssetSearch = (query: string, chainId?: ChainId) => {
150
- const { data: assets, ...rest } = useAssets()
151
-
152
- const searchResults = (() => {
153
- let filtered = chainId ? assets.filter(a => a.chainId === chainId) : assets
154
-
155
- if (!query.trim()) {
156
- const natives = filtered.filter(a => isNativeAsset(a.assetId))
157
- const others = filtered.filter(a => !isNativeAsset(a.assetId)).slice(0, 50 - natives.length)
158
- return [...natives, ...others]
159
- }
160
-
161
- const lowerQuery = query.toLowerCase()
162
-
163
- const matched = filtered
164
- .filter(asset => {
165
- return (
166
- asset.symbol.toLowerCase().includes(lowerQuery) ||
167
- asset.name.toLowerCase().includes(lowerQuery) ||
168
- asset.assetId.toLowerCase().includes(lowerQuery)
169
- )
170
- })
171
- .map(asset => ({ asset, score: scoreAsset(asset, query) }))
172
- .sort((a, b) => b.score - a.score)
173
- .slice(0, 100)
174
- .map(item => item.asset)
175
-
176
- return matched
177
- })()
178
-
179
- return { data: searchResults, ...rest }
180
- }