@zerodev/smart-routing-address-react-ui 0.0.1
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 +117 -0
- package/dist/_types/components/AddressDisplay/index.d.ts +43 -0
- package/dist/_types/components/AddressDisplay/index.d.ts.map +1 -0
- package/dist/_types/components/ErrorRetryCard/index.d.ts +21 -0
- package/dist/_types/components/ErrorRetryCard/index.d.ts.map +1 -0
- package/dist/_types/components/FeeBreakdown/feeInfo.d.ts +24 -0
- package/dist/_types/components/FeeBreakdown/feeInfo.d.ts.map +1 -0
- package/dist/_types/components/FeeBreakdown/index.d.ts +28 -0
- package/dist/_types/components/FeeBreakdown/index.d.ts.map +1 -0
- package/dist/_types/components/LoadingCard/index.d.ts +6 -0
- package/dist/_types/components/LoadingCard/index.d.ts.map +1 -0
- package/dist/_types/components/PendingDeposits/index.d.ts +14 -0
- package/dist/_types/components/PendingDeposits/index.d.ts.map +1 -0
- package/dist/_types/components/QrSheet/QrCode.d.ts +28 -0
- package/dist/_types/components/QrSheet/QrCode.d.ts.map +1 -0
- package/dist/_types/components/QrSheet/index.d.ts +16 -0
- package/dist/_types/components/QrSheet/index.d.ts.map +1 -0
- package/dist/_types/components/TxnItem/ExplorerLink.d.ts +16 -0
- package/dist/_types/components/TxnItem/ExplorerLink.d.ts.map +1 -0
- package/dist/_types/components/TxnItem/index.d.ts +19 -0
- package/dist/_types/components/TxnItem/index.d.ts.map +1 -0
- package/dist/_types/constants.d.ts +20 -0
- package/dist/_types/constants.d.ts.map +1 -0
- package/dist/_types/context/SmartRoutingAddressContext.d.ts +32 -0
- package/dist/_types/context/SmartRoutingAddressContext.d.ts.map +1 -0
- package/dist/_types/context/SmartRoutingAddressProvider.d.ts +13 -0
- package/dist/_types/context/SmartRoutingAddressProvider.d.ts.map +1 -0
- package/dist/_types/hooks/useCreateSmartRoutingAddress.d.ts +23 -0
- package/dist/_types/hooks/useCreateSmartRoutingAddress.d.ts.map +1 -0
- package/dist/_types/hooks/useDepositStatus.d.ts +25 -0
- package/dist/_types/hooks/useDepositStatus.d.ts.map +1 -0
- package/dist/_types/hooks/useNewDeposits.d.ts +8 -0
- package/dist/_types/hooks/useNewDeposits.d.ts.map +1 -0
- package/dist/_types/hooks/useProviderFees.d.ts +22 -0
- package/dist/_types/hooks/useProviderFees.d.ts.map +1 -0
- package/dist/_types/hooks/useSmartRoutingAddress.d.ts +20 -0
- package/dist/_types/hooks/useSmartRoutingAddress.d.ts.map +1 -0
- package/dist/_types/iconAssets.d.ts +7 -0
- package/dist/_types/iconAssets.d.ts.map +1 -0
- package/dist/_types/index.d.ts +14 -0
- package/dist/_types/index.d.ts.map +1 -0
- package/dist/_types/pages/Deposit.d.ts +12 -0
- package/dist/_types/pages/Deposit.d.ts.map +1 -0
- package/dist/_types/pages/PastDeposits.d.ts +14 -0
- package/dist/_types/pages/PastDeposits.d.ts.map +1 -0
- package/dist/_types/pages/TransactionDetails.d.ts +11 -0
- package/dist/_types/pages/TransactionDetails.d.ts.map +1 -0
- package/dist/_types/pages/index.d.ts +25 -0
- package/dist/_types/pages/index.d.ts.map +1 -0
- package/dist/_types/types.d.ts +75 -0
- package/dist/_types/types.d.ts.map +1 -0
- package/dist/_types/utils/chains.d.ts +8 -0
- package/dist/_types/utils/chains.d.ts.map +1 -0
- package/dist/_types/utils/config.d.ts +35 -0
- package/dist/_types/utils/config.d.ts.map +1 -0
- package/dist/_types/utils/deposits.d.ts +29 -0
- package/dist/_types/utils/deposits.d.ts.map +1 -0
- package/dist/_types/utils/fees.d.ts +14 -0
- package/dist/_types/utils/fees.d.ts.map +1 -0
- package/dist/_types/utils/format.d.ts +27 -0
- package/dist/_types/utils/format.d.ts.map +1 -0
- package/dist/_types/utils/providerFees.d.ts +103 -0
- package/dist/_types/utils/providerFees.d.ts.map +1 -0
- package/dist/index.cjs +2 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.mjs +2180 -0
- package/dist/index.mjs.map +1 -0
- package/dist/styles.css +2 -0
- package/package.json +91 -0
- package/src/components/AddressDisplay/index.tsx +108 -0
- package/src/components/ErrorRetryCard/index.tsx +68 -0
- package/src/components/FeeBreakdown/feeInfo.ts +25 -0
- package/src/components/FeeBreakdown/index.tsx +218 -0
- package/src/components/LoadingCard/index.tsx +27 -0
- package/src/components/PendingDeposits/index.tsx +152 -0
- package/src/components/QrSheet/QrCode.tsx +163 -0
- package/src/components/QrSheet/index.tsx +80 -0
- package/src/components/TxnItem/ExplorerLink.tsx +37 -0
- package/src/components/TxnItem/index.tsx +178 -0
- package/src/constants.ts +102 -0
- package/src/context/SmartRoutingAddressContext.ts +48 -0
- package/src/context/SmartRoutingAddressProvider.tsx +145 -0
- package/src/hooks/useCreateSmartRoutingAddress.ts +28 -0
- package/src/hooks/useDepositStatus.ts +110 -0
- package/src/hooks/useNewDeposits.ts +25 -0
- package/src/hooks/useProviderFees.ts +235 -0
- package/src/hooks/useSmartRoutingAddress.ts +25 -0
- package/src/iconAssets.ts +130 -0
- package/src/index.ts +27 -0
- package/src/pages/Deposit.tsx +605 -0
- package/src/pages/PastDeposits.tsx +232 -0
- package/src/pages/TransactionDetails.tsx +466 -0
- package/src/pages/index.tsx +165 -0
- package/src/types.ts +84 -0
- package/src/utils/chains.ts +26 -0
- package/src/utils/config.ts +142 -0
- package/src/utils/deposits.ts +106 -0
- package/src/utils/fees.ts +51 -0
- package/src/utils/format.ts +108 -0
- package/src/utils/providerFees.ts +301 -0
package/dist/styles.css
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/*! tailwindcss v4.3.2 | MIT License | https://tailwindcss.com */
|
|
2
|
+
@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial}}}@layer theme{:root,:host{--zd-font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--zd-color-gray-700:oklch(37.3% .034 259.733);--zd-color-gray-900:oklch(21% .034 264.665);--zd-color-white:#fff;--zd-spacing:.25rem;--zd-text-sm--line-height:calc(1.25 / .875);--zd-text-base--line-height:calc(1.5 / 1);--zd-text-lg--line-height:calc(1.75 / 1.125);--zd-text-2xl--line-height:calc(2 / 1.5);--zd-font-weight-medium:500;--zd-font-weight-semibold:600;--zd-font-weight-bold:700;--zd-radius-sm:.25rem;--zd-radius-md:.375rem;--zd-radius-lg:.5rem;--zd-radius-xl:.75rem;--zd-radius-2xl:1rem;--zd-radius-3xl:1.5rem;--zd-radius-4xl:2rem;--zd-animate-spin:spin 1s linear infinite;--zd-default-transition-duration:.15s;--zd-default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--zd-default-font-family:sans-serif;--zd-default-mono-font-family:var(--zd-font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--zd-default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--zd-default-font-feature-settings,normal);font-variation-settings:var(--zd-default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--zd-default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--zd-default-mono-font-feature-settings,normal);font-variation-settings:var(--zd-default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.zd\:pointer-events-none{pointer-events:none}.zd\:sr-only{clip-path:inset(50%);white-space:nowrap;border-width:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.zd\:absolute{position:absolute}.zd\:relative{position:relative}.zd\:inset-0{inset:0}.zd\:top-0{top:0}.zd\:top-1\/2{top:50%}.zd\:right-0{right:0}.zd\:right-1{right:var(--zd-spacing)}.zd\:right-3{right:calc(var(--zd-spacing) * 3)}.zd\:bottom-0{bottom:0}.zd\:bottom-1{bottom:var(--zd-spacing)}.zd\:left-0{left:0}.zd\:left-1{left:var(--zd-spacing)}.zd\:left-1\/2{left:50%}.zd\:isolate{isolation:isolate}.zd\:z-0{z-index:0}.zd\:z-10{z-index:10}.zd\:z-20{z-index:20}.zd\:z-50{z-index:50}.zd\:m-1\.5{margin:calc(var(--zd-spacing) * 1.5)}.zd\:-mx-4{margin-inline:calc(var(--zd-spacing) * -4)}.zd\:mx-2{margin-inline:calc(var(--zd-spacing) * 2)}.zd\:my-1{margin-block:var(--zd-spacing)}.zd\:mt-1{margin-top:var(--zd-spacing)}.zd\:mb-2{margin-bottom:calc(var(--zd-spacing) * 2)}.zd\:-ml-4{margin-left:calc(var(--zd-spacing) * -4)}.zd\:block{display:block}.zd\:flex{display:flex}.zd\:inline-block{display:inline-block}.zd\:inline-flex{display:inline-flex}.zd\:size-3{width:calc(var(--zd-spacing) * 3);height:calc(var(--zd-spacing) * 3)}.zd\:size-3\.5{width:calc(var(--zd-spacing) * 3.5);height:calc(var(--zd-spacing) * 3.5)}.zd\:size-4{width:calc(var(--zd-spacing) * 4);height:calc(var(--zd-spacing) * 4)}.zd\:size-5{width:calc(var(--zd-spacing) * 5);height:calc(var(--zd-spacing) * 5)}.zd\:size-8\.5{width:calc(var(--zd-spacing) * 8.5);height:calc(var(--zd-spacing) * 8.5)}.zd\:size-11{width:calc(var(--zd-spacing) * 11);height:calc(var(--zd-spacing) * 11)}.zd\:size-full{width:100%;height:100%}.zd\:h-2\.5{height:calc(var(--zd-spacing) * 2.5)}.zd\:h-3{height:calc(var(--zd-spacing) * 3)}.zd\:h-3\.5{height:calc(var(--zd-spacing) * 3.5)}.zd\:h-4{height:calc(var(--zd-spacing) * 4)}.zd\:h-4\.5{height:calc(var(--zd-spacing) * 4.5)}.zd\:h-5{height:calc(var(--zd-spacing) * 5)}.zd\:h-6{height:calc(var(--zd-spacing) * 6)}.zd\:h-7{height:calc(var(--zd-spacing) * 7)}.zd\:h-9{height:calc(var(--zd-spacing) * 9)}.zd\:h-10{height:calc(var(--zd-spacing) * 10)}.zd\:h-11{height:calc(var(--zd-spacing) * 11)}.zd\:h-12{height:calc(var(--zd-spacing) * 12)}.zd\:h-13{height:calc(var(--zd-spacing) * 13)}.zd\:h-16{height:calc(var(--zd-spacing) * 16)}.zd\:h-17{height:calc(var(--zd-spacing) * 17)}.zd\:h-32{height:calc(var(--zd-spacing) * 32)}.zd\:h-202\.5{height:calc(var(--zd-spacing) * 202.5)}.zd\:h-\[52px\]{height:52px}.zd\:h-\[68px\]{height:68px}.zd\:h-\[84px\]{height:84px}.zd\:h-\[240px\]{height:240px}.zd\:h-full{height:100%}.zd\:h-px{height:1px}.zd\:max-h-80{max-height:calc(var(--zd-spacing) * 80)}.zd\:max-h-full{max-height:100%}.zd\:min-h-0{min-height:0}.zd\:min-h-11{min-height:calc(var(--zd-spacing) * 11)}.zd\:w-2\.5{width:calc(var(--zd-spacing) * 2.5)}.zd\:w-3{width:calc(var(--zd-spacing) * 3)}.zd\:w-3\.5{width:calc(var(--zd-spacing) * 3.5)}.zd\:w-4{width:calc(var(--zd-spacing) * 4)}.zd\:w-5{width:calc(var(--zd-spacing) * 5)}.zd\:w-6{width:calc(var(--zd-spacing) * 6)}.zd\:w-9{width:calc(var(--zd-spacing) * 9)}.zd\:w-10{width:calc(var(--zd-spacing) * 10)}.zd\:w-11{width:calc(var(--zd-spacing) * 11)}.zd\:w-12{width:calc(var(--zd-spacing) * 12)}.zd\:w-13{width:calc(var(--zd-spacing) * 13)}.zd\:w-14{width:calc(var(--zd-spacing) * 14)}.zd\:w-16{width:calc(var(--zd-spacing) * 16)}.zd\:w-20{width:calc(var(--zd-spacing) * 20)}.zd\:w-24{width:calc(var(--zd-spacing) * 24)}.zd\:w-72{width:calc(var(--zd-spacing) * 72)}.zd\:w-80{width:calc(var(--zd-spacing) * 80)}.zd\:w-100{width:calc(var(--zd-spacing) * 100)}.zd\:w-\[52px\]{width:52px}.zd\:w-\[240px\]{width:240px}.zd\:w-auto{width:auto}.zd\:w-full{width:100%}.zd\:w-px{width:1px}.zd\:max-w-\[220px\]{max-width:220px}.zd\:max-w-\[230px\]{max-width:230px}.zd\:max-w-\[300px\]{max-width:300px}.zd\:max-w-full{max-width:100%}.zd\:min-w-0{min-width:0}.zd\:flex-1{flex:1}.zd\:shrink-0{flex-shrink:0}.zd\:-translate-x-1\/2{--tw-translate-x:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.zd\:-translate-y-1\/2{--tw-translate-y:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.zd\:animate-fee-flash{animation:.42s cubic-bezier(.2,.9,.3,1) both fee-flash}.zd\:animate-skel-pulse{animation:1.1s ease-in-out infinite skel-pulse}.zd\:animate-spin{animation:var(--zd-animate-spin)}.zd\:cursor-help{cursor:help}.zd\:cursor-not-allowed{cursor:not-allowed}.zd\:cursor-pointer{cursor:pointer}.zd\:resize-none{resize:none}.zd\:flex-col{flex-direction:column}.zd\:flex-row{flex-direction:row}.zd\:flex-wrap{flex-wrap:wrap}.zd\:items-center{align-items:center}.zd\:items-end{align-items:flex-end}.zd\:items-start{align-items:flex-start}.zd\:justify-between{justify-content:space-between}.zd\:justify-center{justify-content:center}.zd\:justify-start{justify-content:flex-start}.zd\:gap-1{gap:var(--zd-spacing)}.zd\:gap-1\.5{gap:calc(var(--zd-spacing) * 1.5)}.zd\:gap-2{gap:calc(var(--zd-spacing) * 2)}.zd\:gap-3{gap:calc(var(--zd-spacing) * 3)}.zd\:gap-4{gap:calc(var(--zd-spacing) * 4)}.zd\:gap-6{gap:calc(var(--zd-spacing) * 6)}.zd\:gap-\[5px\]{gap:5px}.zd\:self-end{align-self:flex-end}.zd\:self-start{align-self:flex-start}.zd\:truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.zd\:overflow-hidden{overflow:hidden}.zd\:overflow-x-hidden{overflow-x:hidden}.zd\:overflow-y-auto{overflow-y:auto}.zd\:rounded-2xl{border-radius:var(--zd-radius-2xl)}.zd\:rounded-3xl{border-radius:var(--zd-radius-3xl)}.zd\:rounded-4xl{border-radius:var(--zd-radius-4xl)}.zd\:rounded-\[4px\]{border-radius:4px}.zd\:rounded-\[14px\]{border-radius:14px}.zd\:rounded-\[32px\]{border-radius:32px}.zd\:rounded-\[38px\]{border-radius:38px}.zd\:rounded-full{border-radius:3.40282e38px}.zd\:rounded-lg{border-radius:var(--zd-radius-lg)}.zd\:rounded-md{border-radius:var(--zd-radius-md)}.zd\:rounded-sm{border-radius:var(--zd-radius-sm)}.zd\:rounded-xl{border-radius:var(--zd-radius-xl)}.zd\:rounded-tl-lg{border-top-left-radius:var(--zd-radius-lg)}.zd\:rounded-tr-lg{border-top-right-radius:var(--zd-radius-lg)}.zd\:rounded-br-lg{border-bottom-right-radius:var(--zd-radius-lg)}.zd\:rounded-bl-lg{border-bottom-left-radius:var(--zd-radius-lg)}.zd\:border{border-style:var(--tw-border-style);border-width:1px}.zd\:border-\[0\.3px\]{border-style:var(--tw-border-style);border-width:.3px}.zd\:border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.zd\:border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.zd\:border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.zd\:border-l{border-left-style:var(--tw-border-style);border-left-width:1px}.zd\:border-greyScale\/10{border-color:oklab(16.9052% .00636494 .00836386/.1)}.zd\:border-greyScale\/30{border-color:oklab(16.9052% .00636494 .00836386/.3)}.zd\:border-offWhite{border-color:#f7f5f0}.zd\:border-white\/0{border-color:var(--zd-color-white)}@supports (color:color-mix(in lab, red, red)){.zd\:border-white\/0{border-color:color-mix(in oklab, var(--zd-color-white) 0%, transparent)}}.zd\:bg-greyScale\/10{background-color:oklab(16.9052% .00636494 .00836386/.1)}.zd\:bg-greyScale\/15{background-color:oklab(16.9052% .00636494 .00836386/.15)}.zd\:bg-greyScale\/20{background-color:oklab(16.9052% .00636494 .00836386/.2)}.zd\:bg-greyScale\/30{background-color:oklab(16.9052% .00636494 .00836386/.3)}.zd\:bg-negative\/10{background-color:oklab(65.8731% .193785 .122031/.1)}.zd\:bg-offWhite\/50{background-color:oklab(97.0302% .000165075 .00696582/.5)}.zd\:bg-orange\/10{background-color:oklab(70.9342% .114827 .116983/.1)}.zd\:bg-positive\/15{background-color:oklab(53.3447% -.133422 .110405/.15)}.zd\:bg-solarOrange{background-color:#e76000}.zd\:bg-solarOrange\/60{background-color:oklab(65.138% .131584 .131685/.6)}.zd\:bg-transparent{background-color:#0000}.zd\:bg-white,.zd\:bg-white\/20{background-color:var(--zd-color-white)}@supports (color:color-mix(in lab, red, red)){.zd\:bg-white\/20{background-color:color-mix(in oklab, var(--zd-color-white) 20%, transparent)}}.zd\:bg-white\/40{background-color:var(--zd-color-white)}@supports (color:color-mix(in lab, red, red)){.zd\:bg-white\/40{background-color:color-mix(in oklab, var(--zd-color-white) 40%, transparent)}}.zd\:bg-white\/60{background-color:var(--zd-color-white)}@supports (color:color-mix(in lab, red, red)){.zd\:bg-white\/60{background-color:color-mix(in oklab, var(--zd-color-white) 60%, transparent)}}.zd\:bg-white\/70{background-color:var(--zd-color-white)}@supports (color:color-mix(in lab, red, red)){.zd\:bg-white\/70{background-color:color-mix(in oklab, var(--zd-color-white) 70%, transparent)}}.zd\:object-contain{object-fit:contain}.zd\:object-cover{object-fit:cover}.zd\:p-0{padding:0}.zd\:p-1{padding:var(--zd-spacing)}.zd\:p-1\.5{padding:calc(var(--zd-spacing) * 1.5)}.zd\:p-2{padding:calc(var(--zd-spacing) * 2)}.zd\:p-4{padding:calc(var(--zd-spacing) * 4)}.zd\:p-5{padding:calc(var(--zd-spacing) * 5)}.zd\:p-6{padding:calc(var(--zd-spacing) * 6)}.zd\:p-px{padding:1px}.zd\:px-0{padding-inline:0}.zd\:px-1{padding-inline:var(--zd-spacing)}.zd\:px-2{padding-inline:calc(var(--zd-spacing) * 2)}.zd\:px-3{padding-inline:calc(var(--zd-spacing) * 3)}.zd\:px-4{padding-inline:calc(var(--zd-spacing) * 4)}.zd\:px-5{padding-inline:calc(var(--zd-spacing) * 5)}.zd\:px-6{padding-inline:calc(var(--zd-spacing) * 6)}.zd\:py-1{padding-block:var(--zd-spacing)}.zd\:py-1\.5{padding-block:calc(var(--zd-spacing) * 1.5)}.zd\:py-2{padding-block:calc(var(--zd-spacing) * 2)}.zd\:py-3{padding-block:calc(var(--zd-spacing) * 3)}.zd\:py-3\.5{padding-block:calc(var(--zd-spacing) * 3.5)}.zd\:py-4{padding-block:calc(var(--zd-spacing) * 4)}.zd\:py-5{padding-block:calc(var(--zd-spacing) * 5)}.zd\:py-8{padding-block:calc(var(--zd-spacing) * 8)}.zd\:pt-0\.5{padding-top:calc(var(--zd-spacing) * .5)}.zd\:pt-4{padding-top:calc(var(--zd-spacing) * 4)}.zd\:pt-6{padding-top:calc(var(--zd-spacing) * 6)}.zd\:pr-1{padding-right:var(--zd-spacing)}.zd\:pr-2{padding-right:calc(var(--zd-spacing) * 2)}.zd\:pb-3{padding-bottom:calc(var(--zd-spacing) * 3)}.zd\:pb-4{padding-bottom:calc(var(--zd-spacing) * 4)}.zd\:pb-6{padding-bottom:calc(var(--zd-spacing) * 6)}.zd\:pl-1{padding-left:var(--zd-spacing)}.zd\:pl-2{padding-left:calc(var(--zd-spacing) * 2)}.zd\:pl-4{padding-left:calc(var(--zd-spacing) * 4)}.zd\:text-center{text-align:center}.zd\:text-left{text-align:left}.zd\:font-roboto{font-family:Roboto,sans-serif}.zd\:font-sans{font-family:sans-serif}.zd\:text-2xl{font-size:calc(20px * var(--zd-density));line-height:var(--tw-leading,var(--zd-text-2xl--line-height))}.zd\:text-base{font-size:calc(14px * var(--zd-density));line-height:var(--tw-leading,var(--zd-text-base--line-height))}.zd\:text-body1{font-size:calc(16px * var(--zd-density));line-height:var(--tw-leading,130%)}.zd\:text-body2{font-size:calc(14px * var(--zd-density));line-height:var(--tw-leading,130%)}.zd\:text-body3{font-size:calc(12px * var(--zd-density));line-height:var(--tw-leading,130%)}.zd\:text-body4{font-size:calc(10px * var(--zd-density));line-height:var(--tw-leading,130%)}.zd\:text-h1{font-size:calc(42px * var(--zd-density));line-height:var(--tw-leading,110%)}.zd\:text-h2{font-size:calc(28px * var(--zd-density));line-height:var(--tw-leading,110%)}.zd\:text-h3{font-size:calc(18px * var(--zd-density));line-height:var(--tw-leading,130%)}.zd\:text-lg{font-size:calc(16px * var(--zd-density));line-height:var(--tw-leading,var(--zd-text-lg--line-height))}.zd\:text-sm{font-size:calc(12px * var(--zd-density));line-height:var(--tw-leading,var(--zd-text-sm--line-height))}.zd\:leading-none{--tw-leading:1;line-height:1}.zd\:font-bold{--tw-font-weight:var(--zd-font-weight-bold);font-weight:var(--zd-font-weight-bold)}.zd\:font-medium{--tw-font-weight:var(--zd-font-weight-medium);font-weight:var(--zd-font-weight-medium)}.zd\:font-semibold{--tw-font-weight:var(--zd-font-weight-semibold);font-weight:var(--zd-font-weight-semibold)}.zd\:break-all{word-break:break-all}.zd\:whitespace-nowrap{white-space:nowrap}.zd\:text-gray-700{color:var(--zd-color-gray-700)}.zd\:text-gray-900{color:var(--zd-color-gray-900)}.zd\:text-greyScale{color:#130e0b}.zd\:text-greyScale\/50{color:oklab(16.9052% .00636494 .00836386/.5)}.zd\:text-greyScale\/60{color:oklab(16.9052% .00636494 .00836386/.6)}.zd\:text-greyScale\/70{color:oklab(16.9052% .00636494 .00836386/.7)}.zd\:text-greyScale\/90{color:oklab(16.9052% .00636494 .00836386/.9)}.zd\:text-negative{color:#ff4221}.zd\:text-orange{color:#f27b3e}.zd\:text-positive{color:#228300}.zd\:text-solarOrange{color:#e76000}.zd\:text-white{color:var(--zd-color-white)}.zd\:caret-gray-900{caret-color:var(--zd-color-gray-900)}.zd\:opacity-50{opacity:.5}.zd\:shadow-\[0_8px_22px_-10px_rgba\(25\,17\,11\,0\.45\)\]{--tw-shadow:0 8px 22px -10px var(--tw-shadow-color,#19110b73);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.zd\:shadow-\[inset_0_-4px_4px_0_rgba\(255\,255\,255\,0\.1\)\,inset_0_3px_4px_0_rgba\(0\,0\,0\,0\.02\)\],.zd\:shadow-\[inset_0_-4px_4px_0_rgba\(255\,255\,255\,0\.10\)\,inset_0_3px_4px_0_rgba\(0\,0\,0\,0\.02\)\]{--tw-shadow:inset 0 -4px 4px 0 var(--tw-shadow-color,#ffffff1a), inset 0 3px 4px 0 var(--tw-shadow-color,#00000005);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.zd\:shadow-\[inset_0_3px_4px_0_rgba\(0\,0\,0\,0\.02\)\,inset_0_-4px_4px_0_rgba\(255\,255\,255\,0\.1\)\]{--tw-shadow:inset 0 3px 4px 0 var(--tw-shadow-color,#00000005), inset 0 -4px 4px 0 var(--tw-shadow-color,#ffffff1a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.zd\:shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.zd\:backdrop-blur-\[15px\]{--tw-backdrop-blur:blur(15px);-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)}.zd\:backdrop-blur-\[30px\]{--tw-backdrop-blur:blur(30px);-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)}.zd\:transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--zd-default-transition-timing-function));transition-duration:var(--tw-duration,var(--zd-default-transition-duration))}.zd\:outline-none{--tw-outline-style:none;outline-style:none}.zd\:placeholder\:text-gray-900\/50::placeholder{color:var(--zd-color-gray-900)}@supports (color:color-mix(in lab, red, red)){.zd\:placeholder\:text-gray-900\/50::placeholder{color:color-mix(in oklab, var(--zd-color-gray-900) 50%, transparent)}}@media (hover:hover){.zd\:hover\:bg-negative\/20:hover{background-color:oklab(65.8731% .193785 .122031/.2)}.zd\:hover\:bg-offWhite\/40:hover{background-color:oklab(97.0302% .000165075 .00696582/.4)}.zd\:hover\:bg-white\/5:hover{background-color:var(--zd-color-white)}@supports (color:color-mix(in lab, red, red)){.zd\:hover\:bg-white\/5:hover{background-color:color-mix(in oklab, var(--zd-color-white) 5%, transparent)}}.zd\:hover\:bg-white\/20:hover{background-color:var(--zd-color-white)}@supports (color:color-mix(in lab, red, red)){.zd\:hover\:bg-white\/20:hover{background-color:color-mix(in oklab, var(--zd-color-white) 20%, transparent)}}.zd\:hover\:bg-white\/30:hover{background-color:var(--zd-color-white)}@supports (color:color-mix(in lab, red, red)){.zd\:hover\:bg-white\/30:hover{background-color:color-mix(in oklab, var(--zd-color-white) 30%, transparent)}}.zd\:hover\:bg-white\/40:hover{background-color:var(--zd-color-white)}@supports (color:color-mix(in lab, red, red)){.zd\:hover\:bg-white\/40:hover{background-color:color-mix(in oklab, var(--zd-color-white) 40%, transparent)}}.zd\:hover\:text-greyScale:hover{color:#130e0b}.zd\:hover\:text-solarOrange:hover{color:#e76000}.zd\:hover\:underline:hover{text-decoration-line:underline}}.zd\:active\:bg-white\/10:active{background-color:var(--zd-color-white)}@supports (color:color-mix(in lab, red, red)){.zd\:active\:bg-white\/10:active{background-color:color-mix(in oklab, var(--zd-color-white) 10%, transparent)}}.zd\:active\:bg-white\/30:active{background-color:var(--zd-color-white)}@supports (color:color-mix(in lab, red, red)){.zd\:active\:bg-white\/30:active{background-color:color-mix(in oklab, var(--zd-color-white) 30%, transparent)}}.zd\:disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.zd\:disabled\:opacity-50:disabled{opacity:.5}.zd\:data-\[highlighted\]\:bg-offWhite\/40[data-highlighted]{background-color:oklab(97.0302% .000165075 .00696582/.4)}.zd\:data-\[state\=checked\]\:bg-offWhite\/60[data-state=checked]{background-color:oklab(97.0302% .000165075 .00696582/.6)}.zd\:data-\[state\=closed\]\:animate-backdrop-out[data-state=closed]{animation:.2s ease-out forwards backdrop-out}.zd\:data-\[state\=closed\]\:animate-sheet-out[data-state=closed]{animation:.25s cubic-bezier(.32,.72,0,1) forwards sheet-out}.zd\:data-\[state\=delayed-open\]\:animate-popper-in[data-state=delayed-open]{animation:.16s ease-out both popper-in}.zd\:data-\[state\=open\]\:pointer-events-auto[data-state=open]{pointer-events:auto}.zd\:data-\[state\=open\]\:animate-backdrop-in[data-state=open]{animation:.2s ease-out forwards backdrop-in}.zd\:data-\[state\=open\]\:animate-popper-in[data-state=open]{animation:.16s ease-out both popper-in}.zd\:data-\[state\=open\]\:animate-sheet-in[data-state=open]{animation:.3s cubic-bezier(.32,.72,0,1) forwards sheet-in}}:root{--zd-density:1}[data-zd-size]{--zd-spacing:calc(.25rem * var(--zd-density))}[data-zd-size=sm]{--zd-density:.8}[data-zd-size=md]{--zd-density:.9}[data-zd-size=lg]{--zd-density:1}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-backdrop-blur{syntax:"*";inherits:false}@property --tw-backdrop-brightness{syntax:"*";inherits:false}@property --tw-backdrop-contrast{syntax:"*";inherits:false}@property --tw-backdrop-grayscale{syntax:"*";inherits:false}@property --tw-backdrop-hue-rotate{syntax:"*";inherits:false}@property --tw-backdrop-invert{syntax:"*";inherits:false}@property --tw-backdrop-opacity{syntax:"*";inherits:false}@property --tw-backdrop-saturate{syntax:"*";inherits:false}@property --tw-backdrop-sepia{syntax:"*";inherits:false}@keyframes spin{to{transform:rotate(360deg)}}@keyframes sheet-in{0%{transform:translateY(100%)}to{transform:translateY(0)}}@keyframes sheet-out{0%{transform:translateY(0)}to{transform:translateY(100%)}}@keyframes backdrop-in{0%{opacity:0}to{opacity:1}}@keyframes backdrop-out{0%{opacity:1}to{opacity:0}}@keyframes skel-pulse{0%,to{opacity:.65}50%{opacity:1}}@keyframes popper-in{0%{opacity:0;transform:scale(.97)translateY(-3px)}to{opacity:1;transform:scale(1)translateY(0)}}@keyframes fee-flash{0%{opacity:0;transform:translateY(-3px)scale(.96)}to{opacity:1;transform:none}}
|
package/package.json
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@zerodev/smart-routing-address-react-ui",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "React hooks, provider, and UI for ZeroDev Smart Routing Address deposits",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "git+https://github.com/zerodevapp/zerodev-wallet-sdk.git",
|
|
8
|
+
"directory": "packages/smart-routing-address-react-ui"
|
|
9
|
+
},
|
|
10
|
+
"sideEffects": [
|
|
11
|
+
"**/*.css"
|
|
12
|
+
],
|
|
13
|
+
"main": "./dist/index.cjs",
|
|
14
|
+
"module": "./dist/index.mjs",
|
|
15
|
+
"types": "./dist/_types/index.d.ts",
|
|
16
|
+
"exports": {
|
|
17
|
+
".": {
|
|
18
|
+
"types": "./dist/_types/index.d.ts",
|
|
19
|
+
"import": "./dist/index.mjs",
|
|
20
|
+
"require": "./dist/index.cjs"
|
|
21
|
+
},
|
|
22
|
+
"./styles.css": "./dist/styles.css"
|
|
23
|
+
},
|
|
24
|
+
"files": [
|
|
25
|
+
"dist",
|
|
26
|
+
"src/**/*.ts",
|
|
27
|
+
"src/**/*.tsx",
|
|
28
|
+
"!dist/**/*.tsbuildinfo",
|
|
29
|
+
"!src/**/*.test.ts",
|
|
30
|
+
"!src/**/*.test.tsx",
|
|
31
|
+
"!src/**/*.stories.ts",
|
|
32
|
+
"!src/**/*.stories.tsx",
|
|
33
|
+
"!src/test/**"
|
|
34
|
+
],
|
|
35
|
+
"keywords": [
|
|
36
|
+
"react",
|
|
37
|
+
"hooks",
|
|
38
|
+
"components",
|
|
39
|
+
"smart-routing",
|
|
40
|
+
"deposit",
|
|
41
|
+
"zerodev",
|
|
42
|
+
"web3"
|
|
43
|
+
],
|
|
44
|
+
"dependencies": {
|
|
45
|
+
"@zerodev/smart-routing-address": "^0.2.5",
|
|
46
|
+
"uqr": "^0.1.2",
|
|
47
|
+
"zod": "^4.4.3",
|
|
48
|
+
"@zerodev/react-ui": "0.0.5"
|
|
49
|
+
},
|
|
50
|
+
"peerDependencies": {
|
|
51
|
+
"react": "^18.0.0 || ^19.0.0",
|
|
52
|
+
"react-dom": "^18.0.0 || ^19.0.0",
|
|
53
|
+
"viem": "^2.47.18"
|
|
54
|
+
},
|
|
55
|
+
"devDependencies": {
|
|
56
|
+
"@storybook/addon-a11y": "^10.3.3",
|
|
57
|
+
"@storybook/addon-docs": "^10.3.3",
|
|
58
|
+
"@storybook/react-vite": "^10.3.3",
|
|
59
|
+
"@tailwindcss/cli": "^4.2.2",
|
|
60
|
+
"@tailwindcss/postcss": "^4.2.2",
|
|
61
|
+
"@testing-library/react": "^16.3.0",
|
|
62
|
+
"@types/react": "~19.2.14",
|
|
63
|
+
"@types/react-dom": "^19",
|
|
64
|
+
"@vitejs/plugin-react": "^4.7.0",
|
|
65
|
+
"@vitest/coverage-v8": "^4.0.18",
|
|
66
|
+
"happy-dom": "^20.6.0",
|
|
67
|
+
"postcss": "^8.5.8",
|
|
68
|
+
"react": "19.2.0",
|
|
69
|
+
"react-dom": "19.2.0",
|
|
70
|
+
"storybook": "^10.3.3",
|
|
71
|
+
"tailwindcss": "^4.2.2",
|
|
72
|
+
"typescript": "5.9.3",
|
|
73
|
+
"viem": "^2.47.18",
|
|
74
|
+
"vite": "^6.4.1",
|
|
75
|
+
"vitest": "^4.0.18"
|
|
76
|
+
},
|
|
77
|
+
"scripts": {
|
|
78
|
+
"build": "pnpm run clean && pnpm run build:css && pnpm run build:js && pnpm run build:types",
|
|
79
|
+
"build:css": "npx @tailwindcss/cli -i ./src/styles.css -o ./dist/styles.css --minify",
|
|
80
|
+
"build:js": "vite build",
|
|
81
|
+
"build:types": "tsc --project ./tsconfig.build.json --outDir ./dist/_types --emitDeclarationOnly --declaration --declarationMap",
|
|
82
|
+
"dev": "tsc --watch",
|
|
83
|
+
"dev:css": "npx @tailwindcss/cli -i ./src/styles.css -o ./dist/styles.css --watch",
|
|
84
|
+
"typecheck": "tsc --noEmit --project ./tsconfig.build.json",
|
|
85
|
+
"clean": "rm -rf dist",
|
|
86
|
+
"test": "vitest run",
|
|
87
|
+
"test:watch": "vitest",
|
|
88
|
+
"storybook": "storybook dev -p 6008",
|
|
89
|
+
"build-storybook": "storybook build"
|
|
90
|
+
}
|
|
91
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { cn, Icon, Text, Wrapper } from '@zerodev/react-ui'
|
|
2
|
+
import type { AddressState } from '../../types'
|
|
3
|
+
import { LoadingCard } from '../LoadingCard'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The card that renders the deposit address in the SRA "Deposit funds" screen.
|
|
7
|
+
*
|
|
8
|
+
* Two visual states, each mapped 1:1 to a Figma node:
|
|
9
|
+
* - Loading (Figma 17634:104343, "Smart Funding" card): delegates to
|
|
10
|
+
* `LoadingCard`, which is the shared spinner+text pill used elsewhere in
|
|
11
|
+
* the SRA flow (e.g., SmartFunding's "Watching for deposit" state).
|
|
12
|
+
* - Ready (Figma 17762:78875, address+QR row): 14px radius, 40% offWhite
|
|
13
|
+
* surface, left-aligned address text + a 52×52 white QR button on the
|
|
14
|
+
* right. Rendered when `address` is supplied.
|
|
15
|
+
*
|
|
16
|
+
* The two states have deliberately different visuals; they share this
|
|
17
|
+
* component because the parent renders the same slot in both cases.
|
|
18
|
+
*/
|
|
19
|
+
export interface AddressDisplayUIProps {
|
|
20
|
+
/** Deposit address to render; when omitted, the loading variant is shown. */
|
|
21
|
+
address?: string
|
|
22
|
+
/**
|
|
23
|
+
* Message rendered in the loading variant. Include chain-specific context
|
|
24
|
+
* from the caller, e.g., `Watching for your deposit on Base…`.
|
|
25
|
+
*/
|
|
26
|
+
loadingText?: string
|
|
27
|
+
/** Handler for the QR icon button (ready variant). */
|
|
28
|
+
onQrClick?: (() => void) | undefined
|
|
29
|
+
className?: string
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function AddressDisplayUI({
|
|
33
|
+
address,
|
|
34
|
+
loadingText = 'Watching for your deposit…',
|
|
35
|
+
onQrClick,
|
|
36
|
+
className,
|
|
37
|
+
}: AddressDisplayUIProps) {
|
|
38
|
+
if (address === undefined) {
|
|
39
|
+
return (
|
|
40
|
+
<LoadingCard
|
|
41
|
+
text={loadingText}
|
|
42
|
+
className={className}
|
|
43
|
+
data-testid="address-display-loading"
|
|
44
|
+
/>
|
|
45
|
+
)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return (
|
|
49
|
+
<Wrapper
|
|
50
|
+
variant="ghost"
|
|
51
|
+
// Figma's 40% offWhite surface — none of Wrapper's white-only variants
|
|
52
|
+
// hit this tint, so override the backgroundColor. Inline style wins
|
|
53
|
+
// over Wrapper's own style prop.
|
|
54
|
+
style={{ backgroundColor: 'rgba(247, 245, 240, 0.4)' }}
|
|
55
|
+
className={cn(
|
|
56
|
+
// Figma: rounded-[14px], pl-16 pr-8 py-8, gap-12 items-center.
|
|
57
|
+
// Height pinned to 68px so the loading and ready variants swap without
|
|
58
|
+
// the layout jumping.
|
|
59
|
+
'zd:relative zd:flex zd:h-[68px] zd:w-full zd:items-center zd:gap-3 zd:overflow-hidden zd:rounded-[14px] zd:pl-4 zd:pr-2 zd:py-2',
|
|
60
|
+
'zd:shadow-[inset_0_-4px_4px_0_rgba(255,255,255,0.1),inset_0_3px_4px_0_rgba(0,0,0,0.02)]',
|
|
61
|
+
className,
|
|
62
|
+
)}
|
|
63
|
+
data-testid="address-display-ready"
|
|
64
|
+
>
|
|
65
|
+
<Text
|
|
66
|
+
className="zd:min-w-0 zd:flex-1 zd:break-all zd:text-body2"
|
|
67
|
+
data-testid="address-display-address"
|
|
68
|
+
>
|
|
69
|
+
{address}
|
|
70
|
+
</Text>
|
|
71
|
+
<button
|
|
72
|
+
type="button"
|
|
73
|
+
onClick={onQrClick}
|
|
74
|
+
aria-label="Show QR code"
|
|
75
|
+
className="zd:flex zd:w-13 zd:h-13 zd:shrink-0 zd:cursor-pointer zd:items-center zd:justify-center zd:rounded-2xl zd:bg-white"
|
|
76
|
+
data-testid="address-display-qr-button"
|
|
77
|
+
>
|
|
78
|
+
<Icon name="qrCode" className="zd:w-5 zd:h-5 zd:text-greyScale" />
|
|
79
|
+
</button>
|
|
80
|
+
</Wrapper>
|
|
81
|
+
)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export interface AddressDisplayProps {
|
|
85
|
+
/** Current address-generation state from the SRA context. */
|
|
86
|
+
status: AddressState['status']
|
|
87
|
+
/** Deposit address, present when `status === 'success'`. */
|
|
88
|
+
address?: string | undefined
|
|
89
|
+
/** Handler for the QR icon button (only meaningful once `address` resolves). */
|
|
90
|
+
onQrClick?: (() => void) | undefined
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* State-driven wrapper around `AddressDisplayUI`. Picks the right variant
|
|
95
|
+
* (loading / ready) based on the SRA address-generation status; the parent
|
|
96
|
+
* page renders `ErrorRetryCard` in the error case instead of this component.
|
|
97
|
+
*/
|
|
98
|
+
export function AddressDisplay({
|
|
99
|
+
status,
|
|
100
|
+
address,
|
|
101
|
+
onQrClick,
|
|
102
|
+
}: AddressDisplayProps) {
|
|
103
|
+
if (status === 'error') return null
|
|
104
|
+
if (status === 'success' && address !== undefined) {
|
|
105
|
+
return <AddressDisplayUI address={address} onQrClick={onQrClick} />
|
|
106
|
+
}
|
|
107
|
+
return <AddressDisplayUI loadingText="Generating deposit address…" />
|
|
108
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { cn, Icon, Text } from '@zerodev/react-ui'
|
|
2
|
+
|
|
3
|
+
export interface ErrorRetryCardProps {
|
|
4
|
+
/** Error copy shown on the left side, e.g. "Failed to create deposit
|
|
5
|
+
* address…" — kept short (Figma design truncates on one line). */
|
|
6
|
+
message: string
|
|
7
|
+
/** Called when the user clicks the refresh affordance. */
|
|
8
|
+
onRetry: () => void
|
|
9
|
+
/** Marks the button as busy while a retry is in flight — disables clicks
|
|
10
|
+
* and spins the icon so back-to-back taps don't stack requests. */
|
|
11
|
+
busy?: boolean
|
|
12
|
+
/** Accessible label for the icon-only refresh button. Defaults to "Retry". */
|
|
13
|
+
retryLabel?: string
|
|
14
|
+
className?: string
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Error banner with an inline retry affordance. Renders as a compact pill
|
|
19
|
+
* matching the Figma spec (`bg-negative/10`, error-red text, right-hand
|
|
20
|
+
* 52×52 refresh button). Used above the "Min deposit" row in the deposit UI
|
|
21
|
+
* to surface address-creation, empty-route and polling failures.
|
|
22
|
+
*/
|
|
23
|
+
export function ErrorRetryCard({
|
|
24
|
+
message,
|
|
25
|
+
onRetry,
|
|
26
|
+
busy,
|
|
27
|
+
retryLabel = 'Retry',
|
|
28
|
+
className,
|
|
29
|
+
}: ErrorRetryCardProps) {
|
|
30
|
+
return (
|
|
31
|
+
<div
|
|
32
|
+
role="alert"
|
|
33
|
+
className={cn(
|
|
34
|
+
'zd:relative zd:flex zd:w-full zd:items-center zd:justify-center zd:gap-3',
|
|
35
|
+
'zd:overflow-hidden zd:rounded-[14px] zd:border-[0.3px] zd:border-offWhite',
|
|
36
|
+
'zd:bg-negative/10 zd:backdrop-blur-[15px] zd:py-2 zd:pr-2 zd:pl-4',
|
|
37
|
+
'zd:shadow-[inset_0_-4px_4px_0_rgba(255,255,255,0.1),inset_0_3px_4px_0_rgba(0,0,0,0.02)]',
|
|
38
|
+
className,
|
|
39
|
+
)}
|
|
40
|
+
>
|
|
41
|
+
<Text className="zd:flex-1 zd:min-w-0 zd:text-body1 zd:font-medium zd:text-negative">
|
|
42
|
+
{message}
|
|
43
|
+
</Text>
|
|
44
|
+
<button
|
|
45
|
+
type="button"
|
|
46
|
+
onClick={onRetry}
|
|
47
|
+
disabled={busy}
|
|
48
|
+
aria-label={retryLabel}
|
|
49
|
+
aria-busy={busy}
|
|
50
|
+
className={cn(
|
|
51
|
+
'zd:inline-flex zd:h-[52px] zd:w-[52px] zd:shrink-0 zd:items-center zd:justify-center',
|
|
52
|
+
'zd:rounded-2xl zd:bg-negative/10 zd:text-negative zd:cursor-pointer',
|
|
53
|
+
'zd:transition-colors zd:hover:bg-negative/20',
|
|
54
|
+
'zd:disabled:cursor-not-allowed zd:disabled:opacity-50',
|
|
55
|
+
)}
|
|
56
|
+
>
|
|
57
|
+
<Icon
|
|
58
|
+
name="rotateRight"
|
|
59
|
+
className={cn(
|
|
60
|
+
'zd:h-6 zd:w-6 zd:text-negative',
|
|
61
|
+
busy && 'zd:animate-spin',
|
|
62
|
+
)}
|
|
63
|
+
aria-hidden
|
|
64
|
+
/>
|
|
65
|
+
</button>
|
|
66
|
+
</div>
|
|
67
|
+
)
|
|
68
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plain-language explanations for each fee/route line, surfaced as tooltips
|
|
3
|
+
* on the info icons in the fee section so users understand what they're
|
|
4
|
+
* charged.
|
|
5
|
+
*/
|
|
6
|
+
export const FEE_INFO = {
|
|
7
|
+
minDeposit: 'Smallest amount this route can process after fees.',
|
|
8
|
+
maxSlippage: 'Maximum price movement allowed during the swap.',
|
|
9
|
+
estimatedFee: 'Estimated swap, bridge, and network costs.',
|
|
10
|
+
readyIn: 'Estimated arrival after the deposit is detected.',
|
|
11
|
+
// Breakdown legs
|
|
12
|
+
provider: 'Bridge provider selected for this route.',
|
|
13
|
+
execution: 'Cost to execute and deliver funds on the destination chain.',
|
|
14
|
+
capital: 'Relayer cost for fronting capital while bridging.',
|
|
15
|
+
destGas: 'Gas to complete delivery on the destination chain.',
|
|
16
|
+
lp: 'Bridge liquidity-provider fee.',
|
|
17
|
+
service: 'Solver fee for filling the route.',
|
|
18
|
+
originGas: 'Gas to submit from the source chain.',
|
|
19
|
+
app: 'Optional application fee.',
|
|
20
|
+
// Transaction progress steps (transaction-details view)
|
|
21
|
+
detected: 'Deposit detected on the source chain.',
|
|
22
|
+
routing: 'Bridge and swap are in progress.',
|
|
23
|
+
completed: 'Funds arrived in the delivery account.',
|
|
24
|
+
failed: 'Deposit could not be completed.',
|
|
25
|
+
} as const
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
import { cn, Icon, Text, Tooltip } from '@zerodev/react-ui'
|
|
2
|
+
import type { ReactNode } from 'react'
|
|
3
|
+
import { PROVIDER_ICONS } from '../../iconAssets'
|
|
4
|
+
import type { FeeBreakdown, FeeLine } from '../../utils/providerFees'
|
|
5
|
+
import { formatFeePct, formatFeeUsd } from '../../utils/providerFees'
|
|
6
|
+
import { FEE_INFO } from './feeInfo'
|
|
7
|
+
|
|
8
|
+
/** Home pages for supported providers, so the name links out */
|
|
9
|
+
const PROVIDER_URLS: Record<string, string> = {
|
|
10
|
+
Across: 'https://across.to',
|
|
11
|
+
Relay: 'https://relay.link',
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export type LiveValueProps = {
|
|
15
|
+
/** While true, the value is being re-quoted: show a spinner */
|
|
16
|
+
loading: boolean
|
|
17
|
+
/** Changes with the value so the flash-in animation re-triggers */
|
|
18
|
+
flashKey: string | number
|
|
19
|
+
children: ReactNode
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* A value that swaps to a spinner while its route is re-quoting, then flashes
|
|
24
|
+
* the fresh value in. Used so a route change visibly recalculates the min
|
|
25
|
+
* deposit / estimated fee rather than silently snapping to new numbers.
|
|
26
|
+
*/
|
|
27
|
+
export function LiveValue({ loading, flashKey, children }: LiveValueProps) {
|
|
28
|
+
if (loading) {
|
|
29
|
+
return (
|
|
30
|
+
<span
|
|
31
|
+
className="zd:inline-flex zd:items-center zd:justify-center zd:text-orange"
|
|
32
|
+
role="img"
|
|
33
|
+
aria-label="Updating estimate"
|
|
34
|
+
>
|
|
35
|
+
<Icon
|
|
36
|
+
name="loading"
|
|
37
|
+
className="zd:w-3.5 zd:h-3.5 zd:animate-spin zd:text-orange"
|
|
38
|
+
aria-hidden
|
|
39
|
+
/>
|
|
40
|
+
</span>
|
|
41
|
+
)
|
|
42
|
+
}
|
|
43
|
+
return (
|
|
44
|
+
<span
|
|
45
|
+
key={flashKey}
|
|
46
|
+
className="zd:inline-flex zd:items-center zd:gap-1.5 zd:animate-fee-flash"
|
|
47
|
+
>
|
|
48
|
+
{children}
|
|
49
|
+
</span>
|
|
50
|
+
)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** Combined fee value: proportional rate (emphasised) + fixed USD cost */
|
|
54
|
+
export function FeeSummary({ breakdown }: { breakdown: FeeBreakdown }) {
|
|
55
|
+
// When the SRA fee can't be priced in USD (non-stable token), show it as a
|
|
56
|
+
// token amount — the partial USD bridge legs must not headline as the total.
|
|
57
|
+
if (breakdown.totalText) {
|
|
58
|
+
return (
|
|
59
|
+
<Text className="zd:whitespace-nowrap zd:font-medium">
|
|
60
|
+
{breakdown.totalText}
|
|
61
|
+
</Text>
|
|
62
|
+
)
|
|
63
|
+
}
|
|
64
|
+
const pct =
|
|
65
|
+
breakdown.ratePct !== null && breakdown.ratePct > 0
|
|
66
|
+
? formatFeePct(breakdown.ratePct)
|
|
67
|
+
: null
|
|
68
|
+
const usd =
|
|
69
|
+
breakdown.flatUsd !== null ? formatFeeUsd(breakdown.flatUsd) : null
|
|
70
|
+
if (!pct && !usd) {
|
|
71
|
+
return <Text className="zd:whitespace-nowrap">—</Text>
|
|
72
|
+
}
|
|
73
|
+
return (
|
|
74
|
+
<span className="zd:inline-flex zd:items-center zd:gap-1 zd:leading-none">
|
|
75
|
+
{pct && (
|
|
76
|
+
<b className="zd:text-body2 zd:font-bold zd:text-greyScale zd:leading-none">
|
|
77
|
+
{pct}
|
|
78
|
+
</b>
|
|
79
|
+
)}
|
|
80
|
+
{pct && usd && (
|
|
81
|
+
<span className="zd:text-body2 zd:text-greyScale/50 zd:leading-none">
|
|
82
|
+
+
|
|
83
|
+
</span>
|
|
84
|
+
)}
|
|
85
|
+
{usd && (
|
|
86
|
+
<span className="zd:text-body2 zd:font-medium zd:text-greyScale/70 zd:leading-none">
|
|
87
|
+
{usd}
|
|
88
|
+
</span>
|
|
89
|
+
)}
|
|
90
|
+
</span>
|
|
91
|
+
)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** Provider name + brand icon, linked to the provider's site when known */
|
|
95
|
+
export function ProviderValue({ provider }: { provider: string }) {
|
|
96
|
+
const url = PROVIDER_URLS[provider]
|
|
97
|
+
const iconUrl = PROVIDER_ICONS[provider]
|
|
98
|
+
const inner = (
|
|
99
|
+
<>
|
|
100
|
+
<Text className="zd:whitespace-nowrap zd:font-medium">{provider}</Text>
|
|
101
|
+
{iconUrl && (
|
|
102
|
+
<img
|
|
103
|
+
src={iconUrl}
|
|
104
|
+
alt=""
|
|
105
|
+
aria-hidden
|
|
106
|
+
className="zd:size-3.5 zd:shrink-0 zd:rounded-[4px] zd:object-cover"
|
|
107
|
+
/>
|
|
108
|
+
)}
|
|
109
|
+
</>
|
|
110
|
+
)
|
|
111
|
+
if (!url) {
|
|
112
|
+
return (
|
|
113
|
+
<span className="zd:inline-flex zd:items-center zd:gap-1">{inner}</span>
|
|
114
|
+
)
|
|
115
|
+
}
|
|
116
|
+
return (
|
|
117
|
+
<a
|
|
118
|
+
className="zd:inline-flex zd:items-center zd:gap-1 zd:text-greyScale zd:hover:underline"
|
|
119
|
+
href={url}
|
|
120
|
+
target="_blank"
|
|
121
|
+
rel="noreferrer"
|
|
122
|
+
>
|
|
123
|
+
{inner}
|
|
124
|
+
</a>
|
|
125
|
+
)
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function InfoMark({ info }: { info: string }) {
|
|
129
|
+
// Real DOM element so Radix's `Tooltip` (via `asChild`) can attach hover /
|
|
130
|
+
// focus handlers and wire `aria-describedby` to its content. Focusable so
|
|
131
|
+
// keyboard users can trigger the tooltip.
|
|
132
|
+
return (
|
|
133
|
+
<Tooltip content={info}>
|
|
134
|
+
{/* button (not span+tabIndex): natively focusable, so keyboard users
|
|
135
|
+
can trigger the tooltip; Radix wires aria-describedby to the
|
|
136
|
+
tooltip copy on hover / focus. `type="button"` keeps it inert
|
|
137
|
+
inside forms. */}
|
|
138
|
+
<button
|
|
139
|
+
type="button"
|
|
140
|
+
aria-label="More info"
|
|
141
|
+
className="zd:inline-flex zd:items-center zd:justify-center zd:cursor-help zd:outline-none zd:bg-transparent"
|
|
142
|
+
>
|
|
143
|
+
<Icon
|
|
144
|
+
name="info"
|
|
145
|
+
className="zd:w-3 zd:h-3 zd:text-greyScale/50"
|
|
146
|
+
aria-hidden
|
|
147
|
+
/>
|
|
148
|
+
</button>
|
|
149
|
+
</Tooltip>
|
|
150
|
+
)
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function LineValue({ line }: { line: FeeLine }) {
|
|
154
|
+
if (line.sponsored) {
|
|
155
|
+
return (
|
|
156
|
+
<Text className="zd:whitespace-nowrap zd:font-medium">Sponsored</Text>
|
|
157
|
+
)
|
|
158
|
+
}
|
|
159
|
+
// Rates are amount-invariant → show percent; flat costs → show USD; fall
|
|
160
|
+
// back to a raw token amount when neither is available.
|
|
161
|
+
const value =
|
|
162
|
+
line.kind === 'rate' && line.pct !== null
|
|
163
|
+
? formatFeePct(line.pct)
|
|
164
|
+
: line.usd !== null
|
|
165
|
+
? formatFeeUsd(line.usd)
|
|
166
|
+
: line.pct !== null
|
|
167
|
+
? formatFeePct(line.pct)
|
|
168
|
+
: (line.text ?? '—')
|
|
169
|
+
return <Text className="zd:whitespace-nowrap zd:font-medium">{value}</Text>
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
function BreakdownRow({
|
|
173
|
+
label,
|
|
174
|
+
info,
|
|
175
|
+
children,
|
|
176
|
+
className,
|
|
177
|
+
}: {
|
|
178
|
+
label: string
|
|
179
|
+
info?: string
|
|
180
|
+
children: ReactNode
|
|
181
|
+
className?: string
|
|
182
|
+
}) {
|
|
183
|
+
return (
|
|
184
|
+
<div
|
|
185
|
+
className={cn(
|
|
186
|
+
'zd:flex zd:w-full zd:items-center zd:gap-1 zd:py-1',
|
|
187
|
+
className,
|
|
188
|
+
)}
|
|
189
|
+
>
|
|
190
|
+
<Text className="zd:whitespace-nowrap zd:text-greyScale/60">{label}</Text>
|
|
191
|
+
{info && <InfoMark info={info} />}
|
|
192
|
+
<div className="zd:min-w-0 zd:flex-1" />
|
|
193
|
+
{children}
|
|
194
|
+
</div>
|
|
195
|
+
)
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/** Itemised fee rows: provider + each fee leg */
|
|
199
|
+
export function FeeBreakdownRows({ breakdown }: { breakdown: FeeBreakdown }) {
|
|
200
|
+
return (
|
|
201
|
+
<div className="zd:flex zd:w-full zd:flex-col zd:pl-2">
|
|
202
|
+
{breakdown.provider && (
|
|
203
|
+
<BreakdownRow label="Provider" info={FEE_INFO.provider}>
|
|
204
|
+
<ProviderValue provider={breakdown.provider} />
|
|
205
|
+
</BreakdownRow>
|
|
206
|
+
)}
|
|
207
|
+
{breakdown.lines.map((line) => (
|
|
208
|
+
<BreakdownRow
|
|
209
|
+
key={line.key}
|
|
210
|
+
label={line.label}
|
|
211
|
+
info={FEE_INFO[line.key as keyof typeof FEE_INFO]}
|
|
212
|
+
>
|
|
213
|
+
<LineValue line={line} />
|
|
214
|
+
</BreakdownRow>
|
|
215
|
+
))}
|
|
216
|
+
</div>
|
|
217
|
+
)
|
|
218
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { cn, Icon, Text, Wrapper } from '@zerodev/react-ui'
|
|
2
|
+
import type { HTMLAttributes } from 'react'
|
|
3
|
+
|
|
4
|
+
export interface LoadingCardProps extends HTMLAttributes<HTMLDivElement> {
|
|
5
|
+
text: string
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function LoadingCard({ text, className, ...rest }: LoadingCardProps) {
|
|
9
|
+
return (
|
|
10
|
+
<Wrapper
|
|
11
|
+
variant="ghost"
|
|
12
|
+
className={cn(
|
|
13
|
+
'zd:relative zd:flex zd:h-[68px] zd:w-full zd:items-center zd:justify-start zd:gap-2 zd:overflow-hidden zd:rounded-2xl zd:px-4',
|
|
14
|
+
'zd:shadow-[inset_0_-4px_4px_0_rgba(255,255,255,0.1),inset_0_3px_4px_0_rgba(0,0,0,0.02)]',
|
|
15
|
+
className,
|
|
16
|
+
)}
|
|
17
|
+
{...rest}
|
|
18
|
+
>
|
|
19
|
+
<Icon
|
|
20
|
+
name="loading"
|
|
21
|
+
className="zd:w-4 zd:h-4 zd:animate-spin zd:text-orange"
|
|
22
|
+
data-testid="loading-card-icon"
|
|
23
|
+
/>
|
|
24
|
+
<Text className="zd:text-body1 zd:text-greyScale/50">{text}</Text>
|
|
25
|
+
</Wrapper>
|
|
26
|
+
)
|
|
27
|
+
}
|