diff --git a/apps/app/public/common.css b/apps/app/public/common.css index f7184b25c..3136f6be7 100644 --- a/apps/app/public/common.css +++ b/apps/app/public/common.css @@ -1 +1 @@ -/*! tailwindcss v3.3.5 | MIT License | https://tailwindcss.com*/*,:after,:before{border:0 solid #e5e7eb;box-sizing:border-box}:after,:before{--tw-content:""}body{line-height:inherit;margin:0}h1{font-size:inherit;font-weight:inherit}a{text-decoration:inherit}a,select{color:inherit}select{font-feature-settings:inherit;font-family:inherit;font-size:100%;font-variation-settings:inherit;font-weight:inherit;line-height:inherit;margin:0;padding:0;text-transform:none}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}h1{margin:0}img,svg{display:block;vertical-align:middle}img{height:auto;max-width:100%}*,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(138,219,201,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(138,219,201,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.absolute{position:absolute}.relative{position:relative}.bottom-2{bottom:.5rem}.right-0{right:0}.top-0{top:0}.m-2{margin:.5rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mt-2{margin-top:.5rem}.flex{display:flex}.h-16{height:4rem}.h-45{height:11.93rem}.h-screen{height:100vh}.w-44{width:11rem}.w-65{width:16.5rem}.flex-col{flex-direction:column}.items-center{align-items:center}.justify-center{justify-content:center}.gap-3{gap:.75rem}.rounded{border-radius:.25rem}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-bl-md{border-bottom-left-radius:.375rem}.rounded-tr{border-top-right-radius:.25rem}.border-2{border-width:2px}.border-solid{border-style:solid}.border-gray-100{--tw-border-opacity:1;border-color:rgb(243 244 246/var(--tw-border-opacity))}.border-neargreen-200{--tw-border-opacity:1;border-color:rgb(51 142 123/var(--tw-border-opacity))}.bg-gray-100{--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity))}.bg-neargreen-200{--tw-bg-opacity:1;background-color:rgb(51 142 123/var(--tw-bg-opacity))}.bg-warning-light{--tw-bg-opacity:1;background-color:rgb(235 199 199/var(--tw-bg-opacity))}.p-1{padding:.25rem}.text-center{text-align:center}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-medium{font-weight:500}.text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))}.text-warning-dark{--tw-text-opacity:1;color:rgb(191 79 79/var(--tw-text-opacity))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.shadow-md{--tw-shadow:0 4px 6px -1px rgba(0,0,0,.1),0 2px 4px -2px rgba(0,0,0,.1);--tw-shadow-colored:0 4px 6px -1px var(--tw-shadow-color),0 2px 4px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)} \ No newline at end of file +/*! tailwindcss v3.3.5 | MIT License | https://tailwindcss.com*/*,:after,:before{border:0 solid #e5e7eb;box-sizing:border-box}:after,:before{--tw-content:""}html{-webkit-text-size-adjust:100%;font-feature-settings:normal;font-family:Manrope,sans-serif;font-variation-settings:normal;line-height:1.5;-moz-tab-size:4;tab-size:4}body{line-height:inherit;margin:0}h1,h2,h3,h4{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b{font-weight:bolder}code{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}button,select{font-feature-settings:inherit;color:inherit;font-family:inherit;font-size:100%;font-variation-settings:inherit;font-weight:inherit;line-height:inherit;margin:0;padding:0;text-transform:none}[type=button],button{-webkit-appearance:button;background-color:transparent;background-image:none}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}h1,h2,h3,h4,p,ul{margin:0}ul{list-style:none;padding:0}button{cursor:pointer}iframe,img,svg{display:block;vertical-align:middle}img{height:auto;max-width:100%}*,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(138,219,201,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(138,219,201,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.pointer-events-none{pointer-events:none}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.inset-0{inset:0}.bottom-2{bottom:.5rem}.right-0{right:0}.right-2{right:.5rem}.top-0{top:0}.top-2{top:.5rem}.-z-50{z-index:-50}.z-10{z-index:10}.z-50{z-index:50}.m-2{margin:.5rem}.-my-1{margin-bottom:-.25rem;margin-top:-.25rem}.mx-auto{margin-left:auto;margin-right:auto}.mb-0{margin-bottom:0}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.ml-1{margin-left:.25rem}.ml-10{margin-left:2.5rem}.ml-2{margin-left:.5rem}.ml-4{margin-left:1rem}.mr-1{margin-right:.25rem}.mr-2{margin-right:.5rem}.mr-3{margin-right:.75rem}.mt-1{margin-top:.25rem}.mt-10{margin-top:2.5rem}.mt-2{margin-top:.5rem}.inline-block{display:inline-block}.flex{display:flex}.inline-flex{display:inline-flex}.h-16{height:4rem}.h-4{height:1rem}.h-45{height:11.93rem}.h-5{height:1.25rem}.h-7{height:1.75rem}.h-72{height:18rem}.h-8{height:2rem}.h-80{height:20rem}.h-auto{height:auto}.h-full{height:100%}.h-screen{height:100vh}.max-h-60{max-height:15rem}.w-20{width:5rem}.w-4{width:1rem}.w-44{width:11rem}.w-5{width:1.25rem}.w-60{width:15rem}.w-65{width:16.5rem}.w-7{width:1.75rem}.w-80{width:20rem}.w-full{width:100%}.max-w-full{max-width:100%}.max-w-xs{max-width:20rem}.flex-1{flex:1 1 0%}.flex-shrink-0{flex-shrink:0}@keyframes pulse{50%{opacity:.5}}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}.cursor-pointer{cursor:pointer}.touch-none{touch-action:none}.select-none{user-select:none}.appearance-none{appearance:none}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.space-x-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(.5rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(.5rem*var(--tw-space-x-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(1rem*var(--tw-space-y-reverse));margin-top:calc(1rem*(1 - var(--tw-space-y-reverse)))}.divide-y>:not([hidden])~:not([hidden]){--tw-divide-y-reverse:0;border-bottom-width:calc(1px*var(--tw-divide-y-reverse));border-top-width:calc(1px*(1 - var(--tw-divide-y-reverse)))}.overflow-hidden,.truncate{overflow:hidden}.truncate{text-overflow:ellipsis;white-space:nowrap}.break-words{overflow-wrap:break-word}.break-all{word-break:break-all}.rounded{border-radius:.25rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-b-lg{border-bottom-left-radius:.5rem;border-bottom-right-radius:.5rem}.rounded-bl-md{border-bottom-left-radius:.375rem}.rounded-tr{border-top-right-radius:.25rem}.border{border-width:1px}.border-2{border-width:2px}.border-b{border-bottom-width:1px}.border-t{border-top-width:1px}.border-solid{border-style:solid}.border-gray-100{--tw-border-opacity:1;border-color:rgb(243 244 246/var(--tw-border-opacity))}.border-neargreen-200{--tw-border-opacity:1;border-color:rgb(51 142 123/var(--tw-border-opacity))}.bg-black{--tw-bg-opacity:1;background-color:rgb(27 27 27/var(--tw-bg-opacity))}.bg-gray-100{--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity))}.bg-gray-200{--tw-bg-opacity:1;background-color:rgb(229 231 235/var(--tw-bg-opacity))}.bg-gray-400{--tw-bg-opacity:1;background-color:rgb(156 163 175/var(--tw-bg-opacity))}.bg-gray-50{--tw-bg-opacity:1;background-color:rgb(249 250 251/var(--tw-bg-opacity))}.bg-green-500{--tw-bg-opacity:1;background-color:rgb(13 73 74/var(--tw-bg-opacity))}.bg-neargreen-200{--tw-bg-opacity:1;background-color:rgb(51 142 123/var(--tw-bg-opacity))}.bg-warning-light{--tw-bg-opacity:1;background-color:rgb(235 199 199/var(--tw-bg-opacity))}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}.bg-opacity-10{--tw-bg-opacity:0.1}.bg-opacity-90{--tw-bg-opacity:0.9}.fill-current{fill:currentColor}.fill-white{fill:#fff}.p-0{padding:0}.p-1{padding:.25rem}.p-3{padding:.75rem}.px-1{padding-left:.25rem;padding-right:.25rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.py-1{padding-bottom:.25rem;padding-top:.25rem}.py-2{padding-bottom:.5rem;padding-top:.5rem}.py-3{padding-bottom:.75rem;padding-top:.75rem}.py-4{padding-bottom:1rem;padding-top:1rem}.pb-2{padding-bottom:.5rem}.pr-2{padding-right:.5rem}.pt-1{padding-top:.25rem}.pt-3{padding-top:.75rem}.pt-4{padding-top:1rem}.text-center{text-align:center}.text-right{text-align:right}.align-middle{vertical-align:middle}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-normal{font-weight:400}.font-semibold{font-weight:600}.font-thin{font-weight:100}.leading-6{line-height:1.5rem}.leading-8{line-height:2rem}.text-black{--tw-text-opacity:1;color:rgb(27 27 27/var(--tw-text-opacity))}.text-blue-600{--tw-text-opacity:1;color:rgb(128 209 191/var(--tw-text-opacity))}.text-gray-400{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}.text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))}.text-gray-600{--tw-text-opacity:1;color:rgb(75 85 99/var(--tw-text-opacity))}.text-gray-700{--tw-text-opacity:1;color:rgb(55 65 81/var(--tw-text-opacity))}.text-green-500{--tw-text-opacity:1;color:rgb(13 73 74/var(--tw-text-opacity))}.text-warning-dark{--tw-text-opacity:1;color:rgb(191 79 79/var(--tw-text-opacity))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.no-underline{text-decoration-line:none}.shadow{--tw-shadow:0 1px 3px 0 rgba(0,0,0,.1),0 1px 2px -1px rgba(0,0,0,.1);--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color)}.shadow,.shadow-lg{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -4px rgba(0,0,0,.1);--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color)}.shadow-md{--tw-shadow:0 4px 6px -1px rgba(0,0,0,.1),0 2px 4px -2px rgba(0,0,0,.1);--tw-shadow-colored:0 4px 6px -1px var(--tw-shadow-color),0 2px 4px -2px var(--tw-shadow-color)}.shadow-md,.shadow-sm{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 2px 0 rgba(0,0,0,.05);--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color)}.outline-none{outline:2px solid transparent;outline-offset:2px}.drop-shadow-md{--tw-drop-shadow:drop-shadow(0 4px 3px rgba(0,0,0,.07)) drop-shadow(0 2px 2px rgba(0,0,0,.06));filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition-colors{transition-duration:.15s;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1)}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)}b{font-weight:600}.soft-shadow{box-shadow:0 2.6px 6.3px rgba(0,0,0,.06),0 6.3px 16px rgba(0,0,0,.04),0 12px 32.6px rgba(0,0,0,.027),0 21.4px 67.2px rgba(0,0,0,.018),0 43px 184px rgba(0,0,0,.011)} \ No newline at end of file diff --git a/apps/app/src/data/bos-components.ts b/apps/app/src/data/bos-components.ts index c636b4b9e..38707ceb0 100644 --- a/apps/app/src/data/bos-components.ts +++ b/apps/app/src/data/bos-components.ts @@ -2,6 +2,7 @@ import type { NetworkId } from '@/utils/types'; type NetworkComponents = { nodeExplorer: string; + account: string; }; export const componentsByNetworkId: Record< @@ -10,9 +11,11 @@ export const componentsByNetworkId: Record< > = { testnet: { nodeExplorer: `${process.env.NEXT_PUBLIC_ACCOUNT_ID}/widget/bos-components.components.NearBlocks.NodeExplorer`, + account: `${process.env.NEXT_PUBLIC_ACCOUNT_ID}/widget/bos-components.components.NearBlocks.Accounts`, }, mainnet: { nodeExplorer: `${process.env.NEXT_PUBLIC_ACCOUNT_ID}/widget/bos-components.components.NearBlocks.NodeExplorer`, + account: `${process.env.NEXT_PUBLIC_ACCOUNT_ID}/widget/bos-components.components.NearBlocks.Accounts`, }, }; diff --git a/apps/app/src/pages/address/[id].tsx b/apps/app/src/pages/address/[id].tsx new file mode 100644 index 000000000..6207aa2e1 --- /dev/null +++ b/apps/app/src/pages/address/[id].tsx @@ -0,0 +1,18 @@ +import { useRouter } from 'next/router'; + +import { VmComponent } from '@/components/vm/VmComponent'; +import { useBosComponents } from '@/hooks/useBosComponents'; + +const Address = () => { + const router = useRouter(); + const { id } = router.query; + const components = useBosComponents(); + + return ( + <> + + + ); +}; + +export default Address; diff --git a/apps/bos-components/.eslintrc.cjs b/apps/bos-components/.eslintrc.cjs index 602346d46..391a75119 100644 --- a/apps/bos-components/.eslintrc.cjs +++ b/apps/bos-components/.eslintrc.cjs @@ -15,5 +15,6 @@ module.exports = { 'react/display-name': 'off', '@next/next/no-img-element': 'off', 'import/no-anonymous-default-export': 'off', + 'react/jsx-no-undef': 'off', }, }; diff --git a/apps/bos-components/build.js b/apps/bos-components/build.js index 1c865f79f..1b03de6d1 100644 --- a/apps/bos-components/build.js +++ b/apps/bos-components/build.js @@ -32,7 +32,7 @@ async function build() { let updatedContent = content; // Regular expression to match the import statement - const importRegex = /import\s+(\w+)\s+from\s+"@\/includes\/([^"]*)";/; + const importRegex = /import\s+(\w+)\s+from\s+'@\/includes\/([^']*)';/; while (true) { const match = updatedContent.match(importRegex); @@ -85,11 +85,11 @@ async function build() { await replaceInFiles({ files: [`${transpiledPathPrefix}/**/*.jsx`], - from: /import\s+(\w+)\s+from\s+"@\/includes\/([^"]*)";/gm, + from: /import\s+(\w+)\s+from\s+'@\/includes\/([^']*)';/gm, to: (_match) => { // extract component name and path to the imported component const [component, componentName, componentPath] = _match.match( - /import\s+(\w+)\s+from\s+"@\/includes\/([^"]*)";/, + /import\s+(\w+)\s+from\s+'@\/includes\/([^']*)';/, ); // read content of the component from the path const fileToPath = `${transpiledPathPrefix}/../includes/${componentPath}.jsx`; @@ -129,7 +129,6 @@ async function build() { 'utf8', ) .replace(/export /g, ''); - extraNames.forEach(function (name) { const functionName = `${name.trim()}`; const regex = new RegExp( @@ -147,6 +146,7 @@ async function build() { }); } } + return fileContent; } catch (error) { console.error('Error in processImports:', error); @@ -156,7 +156,7 @@ async function build() { await replaceInFiles({ files: [`${transpiledPathPrefix}/**/*.jsx`], - from: /import\s+{[^}]*}\s+from\s+"@\/includes\/([^"]*)";/gm, + from: /import\s+{[^}]*}\s+from\s+'@\/includes\/([^']*)';/gm, to: (_match, importPath) => { const extractedNames = _match .match(/\{([^}]*)\}/)[1] // Get the content inside curly braces @@ -171,23 +171,24 @@ async function build() { ) .replace(/export /g, ''); let contentImport = ''; + let fileImported = ''; // loops through each function name to extract function content - extractedNames.forEach(function (name) { + extractedNames.forEach(function (name, index) { const functionName = `${name.trim()}`; const regex = new RegExp( - `function ${functionName}\\s*\\([^)]*\\)\\s*{((?:[^{}]*|{[^{}]*})*?)}`, + `function\\s+${functionName}\\s*\\([^)]*\\)\\s*{([^]*)}`, + 's', ); - // extract the function body that matches the name from the file content - const functionMatch = importedFileContent.match(regex); - if (functionMatch) { - contentImport += functionMatch[0] + '\n'; + + const match = importedFileContent.match(regex); + if (match) { + contentImport = match[0] + '\n'; } // check if any imported functions used in the etracted content - contentImport = processFileImports(contentImport, importedFileContent); + fileImported += processFileImports(contentImport, importedFileContent); }); - - return `/* INCLUDE: "includes/${importPath}.jsx" */\n${contentImport}/* END_INCLUDE: "includes/${importPath}.jsx" */`; + return `/* INCLUDE: "includes/${importPath}.jsx" */\n${fileImported}/* END_INCLUDE: "includes/${importPath}.jsx" */`; }, }); diff --git a/apps/bos-components/global.d.ts b/apps/bos-components/global.d.ts index 983b98bfc..dc811efaa 100644 --- a/apps/bos-components/global.d.ts +++ b/apps/bos-components/global.d.ts @@ -1,6 +1,6 @@ declare const Widget: (params: { src: string; - props: object; + props?: object; }) => React.ReactNode; declare const useState: ( @@ -13,3 +13,9 @@ declare const useEffect: ( declare const styled; declare const asyncFetch; +declare const Big; +declare const Popover; +declare const Tooltip; +declare const Dialog; +declare const Select; +declare const ScrollArea; diff --git a/apps/bos-components/src/components/NearBlocks/Accounts.tsx b/apps/bos-components/src/components/NearBlocks/Accounts.tsx new file mode 100644 index 000000000..7695116ba --- /dev/null +++ b/apps/bos-components/src/components/NearBlocks/Accounts.tsx @@ -0,0 +1,743 @@ +/** + * Component : Accounts + * License : Business Source License 1.1 + * Description: Accounts component enable users to view information related to their accounts. + * @interface Props + * @param {string} [id] - The account identifier passed as a string. + * @param {boolean} [useStyles] - Flag indicating whether to apply default gateway styles; when set to `true`, the component uses default styles, otherwise, it allows for custom styling. + */ + +interface Props { + id?: string; + useStyles?: boolean; +} + +import Skelton from '@/includes/Common/Skelton'; +import FaExternalLinkAlt from '@/includes/icons/FaExternalLinkAlt'; +import { + yoctoToNear, + fiatValue, + nanoToMilli, + shortenAddress, +} from '@/includes/libs'; +import { + dollarFormat, + localFormat, + weight, + convertToUTC, +} from '@/includes/formats'; +import TokenImage from '@/includes/icons/TokenImage'; +import TokenHoldings from '@/includes/Common/TokenHoldings'; +import { encodeArgs, decodeArgs } from '@/includes/near'; +import { + SatsInfo, + AccountInfo, + DeploymentsInfo, + TokenInfo, + InventoryInfo, + FtsInfo, + ContractCodeInfo, + AccessKeyInfo, + ContractInfo, + FtInfo, + MetaInfo, +} from '@/includes/types'; + +export default function (props: Props) { + const [loading, setLoading] = useState(false); + const [statsData, setStatsData] = useState({} as SatsInfo); + const [accountData, setAccountData] = useState( + {} as AccountInfo, + ); + const [deploymentData, setDeploymentData] = useState( + {} as DeploymentsInfo, + ); + const [tokenData, setTokenData] = useState({} as TokenInfo); + const [inventoryData, setInventoryData] = useState( + {} as InventoryInfo, + ); + const [contract, setContract] = useState({} as ContractInfo); + const [ft, setFT] = useState({} as FtInfo); + const [code, setCode] = useState({} as ContractCodeInfo); + const [key, setKey] = useState({} as AccessKeyInfo); + const [css, setCss] = useState({}); + + function getConfig(network: string) { + switch (network) { + case 'mainnet': + return { + ownerId: 'nearblocks.near', + nodeUrl: 'https://rpc.mainnet.near.org', + backendUrl: 'https://api.nearblocks.io/v1/', + rpcUrl: 'https://archival-rpc.testnet.near.org', + appUrl: 'https://nearblocks.io/', + }; + case 'testnet': + return { + ownerId: 'nearblocks.testnet', + nodeUrl: 'https://rpc.testnet.near.org', + backendUrl: 'https://api-testnet.nearblocks.io/v1/', + rpcUrl: 'https://archival-rpc.testnet.near.org', + appUrl: 'https://testnet.nearblocks.io/', + }; + default: + return {}; + } + } + + /** + * Fetches styles asynchronously from a nearblocks gateway. + */ + function fetchStyle() { + asyncFetch('https://beta.nearblocks.io/common.css').then( + (res: { body: string }) => { + if (res?.body) { + setCss(res.body); + } + }, + ); + } + + const config = getConfig(context.networkId); + + function fetchStatsData() { + //@ts-ignore + asyncFetch(`${config?.backendUrl}stats`, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + }, + }) + .then( + (data: { + body: { + stats: SatsInfo[]; + }; + }) => { + const statsResp = data?.body?.stats?.[0]; + setStatsData({ near_price: statsResp.near_price }); + }, + ) + .catch() + .finally(() => {}); + } + + function fetchAccountData() { + //@ts-ignore + asyncFetch(`${config?.backendUrl}account/${props.id}`, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + }, + }) + .then( + (data: { + body: { + account: AccountInfo[]; + }; + }) => { + const accountResp = data?.body?.account?.[0]; + setAccountData({ + account_id: accountResp.account_id, + amount: accountResp.amount, + code_hash: accountResp.code_hash, + created: accountResp.created, + deleted: accountResp.deleted, + locked: accountResp.locked, + storage_usage: accountResp.storage_usage, + }); + }, + ) + .catch(); + } + + function fetchContractData() { + //@ts-ignore + asyncFetch( + `${config?.backendUrl}account/${props.id}/contract/deployments`, + { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + }, + }, + ) + .then( + (data: { + body: { + deployments: DeploymentsInfo[]; + }; + }) => { + const depResp = data?.body?.deployments?.[0]; + setDeploymentData({ + block_timestamp: depResp.block_timestamp, + receipt_predecessor_account_id: + depResp.receipt_predecessor_account_id, + transaction_hash: depResp.transaction_hash, + }); + }, + ) + .catch(); + } + + function fetchTokenData() { + //@ts-ignore + asyncFetch(`${config?.backendUrl}fts/${props.id}`, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + }, + }) + .then( + (data: { + body: { + contracts: TokenInfo[]; + }; + }) => { + const tokenResp = data?.body?.contracts?.[0]; + setTokenData({ + name: tokenResp.name, + icon: tokenResp.icon, + symbol: tokenResp.symbol, + price: tokenResp.price, + website: tokenResp.website, + }); + }, + ) + .catch() + .finally(() => {}); + } + + function fetchInventoryData() { + //@ts-ignore + asyncFetch(`${config?.backendUrl}account/${props.id}/inventory`, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + }, + }) + .then( + (data: { + body: { + inventory: InventoryInfo; + }; + }) => { + const response = data?.body?.inventory; + setInventoryData({ + fts: response.fts, + nfts: response.nfts, + }); + }, + ) + .catch(); + } + + useEffect(() => { + fetchStatsData(); + fetchAccountData(); + fetchContractData(); + fetchTokenData(); + fetchInventoryData(); + }, []); + + function ftBalanceOf(contracts: string, account_id?: string) { + //@ts-ignore + return asyncFetch(`${config?.rpcUrl}`, { + method: 'POST', + body: JSON.stringify({ + jsonrpc: '2.0', + id: 'dontcare', + method: 'query', + params: { + request_type: 'call_function', + finality: 'final', + account_id: contracts, + method_name: 'ft_balance_of', + args_base64: encodeArgs({ account_id }), + }, + }), + headers: { + 'Content-Type': 'application/json', + }, + }) + .then( + (res: { + body: { + result: { result: number[] }; + }; + }) => { + return res; + }, + ) + .then( + (data: { + body: { + result: { result: number[] }; + }; + }) => { + console.log('dff', data); + const resp = data?.body?.result; + return decodeArgs(resp.result); + }, + ) + .catch((error: any) => { + console.log(error); + }); + } + + useEffect(() => { + function loadBalances() { + const fts = inventoryData.fts; + if (!fts?.length) { + if (fts?.length === 0) setLoading(false); + return; + } + + let total = Big(0); + + const tokens: { + amount: number; + contract: string; + ft_meta: MetaInfo; + rpcAmount: number; + amountUsd: number; + }[] = []; + + const pricedTokens: { + amount: number; + contract: string; + ft_meta: MetaInfo; + rpcAmount: number; + amountUsd: number; + }[] = []; + + Promise.all( + fts.map((ft: FtsInfo) => { + return ftBalanceOf(ft.contract, props.id).then((rslt: string) => { + return { ...ft, amount: rslt }; + }); + }), + ).then((results: FtsInfo[]) => { + results.forEach((rslt: FtsInfo) => { + const ftrslt = rslt; + const amount = rslt?.amount; + + let sum = Big(0); + + let rpcAmount = Big(0); + + if (amount) { + rpcAmount = Big(amount).div(Big(10).pow(ftrslt.ft_meta?.decimals)); + } + + if (ftrslt.ft_meta?.price) { + sum = rpcAmount.mul(Big(ftrslt.ft_meta?.price)); + total = total.add(sum); + + return pricedTokens.push({ + ...ftrslt, + amountUsd: sum.toString(), + rpcAmount: rpcAmount.toString(), + }); + } + + return tokens.push({ + ...ftrslt, + amountUsd: sum.toString(), + rpcAmount: rpcAmount.toString(), + }); + }); + + tokens.sort((a, b) => { + const first = Big(a.rpcAmount); + + const second = Big(b.rpcAmount); + + if (first.lt(second)) return 1; + if (first.gt(second)) return -1; + + return 0; + }); + + pricedTokens.sort((a, b) => { + const first = Big(a.amountUsd); + + const second = Big(b.amountUsd); + + if (first.lt(second)) return 1; + if (first.gt(second)) return -1; + + return 0; + }); + setFT({ + amount: total.toString(), + tokens: [...pricedTokens, ...tokens], + }); + + setLoading(false); + }); + } + + loadBalances(); + }, [inventoryData?.fts, props.id]); + + function contractCode(address: string) { + //@ts-ignore + asyncFetch(`${config?.rpcUrl}`, { + method: 'POST', + body: JSON.stringify({ + jsonrpc: '2.0', + id: 'dontcare', + method: 'query', + params: { + request_type: 'view_code', + finality: 'final', + account_id: address, + prefix_base64: '', + }, + }), + headers: { + 'Content-Type': 'application/json', + }, + }) + .then( + (res: { + body: { + result: ContractCodeInfo; + }; + }) => { + const resp = res?.body?.result; + setCode({ + block_hash: resp.block_hash, + block_height: resp.block_height, + code_base64: resp.code_base64, + hash: resp.hash, + }); + }, + ) + .catch(() => {}); + } + + function viewAccessKeys(address: string) { + //@ts-ignore + asyncFetch(`${config?.rpcUrl}`, { + method: 'POST', + body: JSON.stringify({ + jsonrpc: '2.0', + id: 'dontcare', + method: 'query', + params: { + request_type: 'view_access_key_list', + finality: 'final', + account_id: address, + }, + }), + headers: { + 'Content-Type': 'application/json', + }, + }) + .then( + (res: { + body: { + result: AccessKeyInfo; + }; + }) => { + const resp = res?.body?.result; + setKey({ + block_hash: resp.block_hash, + block_height: resp.block_height, + keys: resp.keys, + hash: resp.hash, + }); + }, + ) + .catch(() => {}); + } + + useEffect(() => { + if (props?.useStyles) fetchStyle(); + }, []); + + const Theme = styled.div` + ${css} + `; + + useEffect(() => { + function loadSchema() { + if (!props.id) return; + + Promise.all([contractCode(props.id), viewAccessKeys(props.id)]); + } + loadSchema(); + }, [props.id]); + + if (code?.code_base64) { + const locked = (key.keys || []).every( + (key: { + access_key: { + nonce: number; + permission: string; + }; + public_key: string; + }) => key.access_key.permission !== 'FullAccess', + ); + + setContract({ ...code, locked }); + } + return ( + +
+
+ {!props.id ? ( + + ) : ( +

+ Near Account: @ {' '} + {props?.id && ( + + {' '} + {' ' + props.id} + + )} + { + + } +

+ )} + { + + } +
+
+ { + + } +
+ +
+
+
+
+

Overview

+ {tokenData?.name && ( +
+
+ {tokenData.name} +
+ {tokenData.website && ( + + + + )} +
+ )} +
+ +
+
+
Balance:
+ {loading ? ( + + ) : ( +
+ {yoctoToNear(accountData?.amount || 0, true)} Ⓝ +
+ )} +
+ {context.networkId === 'mainnet' && statsData?.near_price && ( +
+
Value
+ {loading ? ( + + ) : ( +
+ $ + {fiatValue( + yoctoToNear(accountData.amount || 0, false), + statsData.near_price, + )}{' '} + + (@ ${dollarFormat(statsData.near_price)} / Ⓝ) + +
+ )} +
+ )} +
+
Tokens:
+
+ +
+
+
+
+
+
+
+

+ Account information +

+ +
+
+
+
Staked Balance:
+ {loading ? ( +
+ +
+ ) : ( +
+ {yoctoToNear(Number(accountData?.locked || 0), true)} Ⓝ +
+ )} +
+
+
Storage Used:
+ {loading ? ( +
+ +
+ ) : ( +
+ {weight(Number(accountData?.storage_usage) || 0)} +
+ )} +
+
+
+
+ {loading ? ( +
+ +
+ ) : ( +
+ {accountData?.deleted?.transaction_hash + ? 'Deleted At:' + : 'Created At:'} +
+ )} + {loading ? ( +
+ +
+ ) : ( +
+ {accountData?.deleted?.transaction_hash + ? convertToUTC( + nanoToMilli(accountData.deleted.block_timestamp), + false, + ) + : accountData?.created?.transaction_hash + ? convertToUTC( + nanoToMilli(accountData.created.block_timestamp), + false, + ) + : accountData?.code_hash + ? 'Genesis' + : 'N/A'} +
+ )} +
+ {contract?.hash ? ( +
+
Contract Locked:
+
+ {contract?.locked ? 'Yes' : 'No'} +
+
+ ) : ( +
+ )} +
+ {deploymentData?.receipt_predecessor_account_id && ( + + )} + {tokenData?.name && ( +
+
+ Token Tracker: +
+
+
+ + + + + {tokenData.name} + + ( + + {tokenData.symbol} + + ) + + + {tokenData.price && ( +
+ (@ ${localFormat(tokenData.price)}) +
+ )} +
+
+
+ )} +
+
+
+
+
+ + ); +} diff --git a/apps/bos-components/src/components/Shared/Buttons.tsx b/apps/bos-components/src/components/Shared/Buttons.tsx new file mode 100644 index 000000000..367a1bc32 --- /dev/null +++ b/apps/bos-components/src/components/Shared/Buttons.tsx @@ -0,0 +1,95 @@ +import QRCodeIcon from '@/includes/icons/QRCodeIcon'; +import QrCode from '@/includes/Common/QrCode'; +import CopyIcon from '@/includes/icons/CopyIcon'; +import CloseCircle from '@/includes/icons/CloseCircle'; + +/** + * @param {string} id - The account identifier passed as a string. + */ + +interface Props { + id: string; +} + +export default function (props: Props) { + const [showTooltip, setShowTooltip] = useState(false); + const onCopyClick = () => { + clipboard.writeText(props.id); + setShowTooltip((t: boolean) => !t); + setTimeout(() => { + setShowTooltip((t: boolean) => !t); + }, 5000); + }; + return ( + <> + + + + + + + + {showTooltip ? 'Copied!' : 'Copy account ID to clipboard'} + + + + + + + + + + + +
+

+ {' '} + {props.id} +

+ + + +
+
+
+ +
+
+
+
+ + ); +} diff --git a/apps/bos-components/src/components/Shared/SponsoredBox.tsx b/apps/bos-components/src/components/Shared/SponsoredBox.tsx new file mode 100644 index 000000000..762ddba90 --- /dev/null +++ b/apps/bos-components/src/components/Shared/SponsoredBox.tsx @@ -0,0 +1,137 @@ +import Trade from '@/includes/Banners/Trade'; +import Earn from '@/includes/Banners/Earn'; +import Store from '@/includes/Banners/Store'; +import ArrowDown from '@/includes/icons/ArrowDown'; + +export default function () { + function getConfig(network: string) { + switch (network) { + case 'mainnet': + return { + ownerId: 'nearblocks.near', + nodeUrl: 'https://rpc.mainnet.near.org', + requestUrl: 'https://api.nearblocks.io/v1/', + rpcUrl: 'https://archival-rpc.testnet.near.org', + appUrl: 'https://nearblocks.io/', + }; + case 'testnet': + return { + ownerId: 'nearblocks.testnet', + nodeUrl: 'https://rpc.testnet.near.org', + requestUrl: 'https://api-testnet.nearblocks.io/v1/', + rpcUrl: 'https://archival-rpc.testnet.near.org', + appUrl: 'https://testnet.nearblocks.io/', + }; + default: + return {}; + } + } + const config = getConfig(context.networkId); + + return ( +
+ + + + + + + Sponsored + +
    +
  • {/* */}
  • +
+
+
+ + + + + + + Sponsored + +
    +
  • + +
  • +
+
+
+ + + + + + + Sponsored + +
    +
  • + +
  • +
+
+
+ + + + + + + Sponsored + +
    +
  • + +
  • +
+
+
+
+ ); +} diff --git a/apps/bos-components/src/components/Shared/SponsoredText.tsx b/apps/bos-components/src/components/Shared/SponsoredText.tsx new file mode 100644 index 000000000..dbc7342eb --- /dev/null +++ b/apps/bos-components/src/components/Shared/SponsoredText.tsx @@ -0,0 +1,62 @@ +/** + * @param {boolean} fromHome - Indicates if the component is rendered from the home. + */ + +interface Props { + fromHome?: boolean; +} +export default function (props: Props) { + interface Sponsored { + title: string; + description: string; + btnText: string; + url: string; + } + const [sponsored, setSponsored] = useState({} as Sponsored); + const sponsoredText = [ + { + title: '1inch -', + description: + 'Store your tokens safely. Go self-custodial with the 1inch Wallet -', + btnText: 'Download now', + url: 'https://1inch.network/Nearblocks_Textad', + }, + { + title: 'Stader Labs -', + description: + 'Get 50%+ APY & Assurance of Fund Safety with NearX Multi-Layer Security | Now Integrated with Burrow | ', + btnText: 'NearX - Live on Aurora & NEAR', + url: 'https://near.staderlabs.com/lt/near?tab=Stake', + }, + ]; + + useEffect( + () => + setSponsored( + sponsoredText[Math.floor(Math.random() * sponsoredText.length)], + ), + [], + ); + + return sponsored ? ( +
+

+ Sponsored: + {sponsored.title}{' '} + {sponsored.description} + + {sponsored.btnText} + +

+
+ ) : null; +} diff --git a/apps/bos-components/src/includes/Banners/Earn.tsx b/apps/bos-components/src/includes/Banners/Earn.tsx new file mode 100644 index 000000000..b433db749 --- /dev/null +++ b/apps/bos-components/src/includes/Banners/Earn.tsx @@ -0,0 +1,35 @@ +/** + * @interface Props + * @param {string} appUrl - The URL of the application. + */ + +interface Props { + appUrl?: string; +} + +const Earn = (props: Props) => { + return ( + + + Stader Labs +

Stader Labs

+
+

+ High DeFi Yields ~21% on NearX with Stader | Multi-Layer Security | Zero + Rewards Loss | $1 Mn Bug Bounty +

+
+ ); +}; + +export default Earn; diff --git a/apps/bos-components/src/includes/Banners/Store.tsx b/apps/bos-components/src/includes/Banners/Store.tsx new file mode 100644 index 000000000..04fe31fa1 --- /dev/null +++ b/apps/bos-components/src/includes/Banners/Store.tsx @@ -0,0 +1,55 @@ +/** + * @interface Props + * @param {string} appUrl - The URL of the application. + */ + +interface Props { + appUrl?: string; +} + +const sponsoredStore = [ + { + title: '1inch Wallet - Your self-custodial vault', + description: + 'Audited by top security firms. Hardware wallet connection. MEV protected. Easy to use, secure and self-custodial. Try the 1inch Wallet now!', + url: 'https://1inch.network/Nearblocks_StoreButton', + image: '/sponsored/1inch.svg', + }, +]; + +const Store = (props: Props) => { + return ( +
+ {sponsoredStore.map((sponsore, i) => ( +
1 && + sponsoredStore.length - 1 !== i && + 'border-b' + }`} + > + + + 1inch - #1 DeFi aggregator +

{sponsore.title}

+
+
+

{sponsore.description}

+
+ ))} +
+ ); +}; + +export default Store; diff --git a/apps/bos-components/src/includes/Banners/Trade.tsx b/apps/bos-components/src/includes/Banners/Trade.tsx new file mode 100644 index 000000000..80643cb07 --- /dev/null +++ b/apps/bos-components/src/includes/Banners/Trade.tsx @@ -0,0 +1,54 @@ +/** + * @interface Props + * @param {string} appUrl - The URL of the application. + */ + +interface Props { + appUrl?: string; +} + +const sponsoredTrade = [ + { + title: 'Ref Finance - #1 AMM on NEAR', + description: + 'Ref Finance is a community-led, multi-purpose DeFi platform built on the NEAR Protocol.', + url: 'https://ref.finance', + }, +]; + +const Trade = (props: Props) => { + return ( +
+ {sponsoredTrade.map((sponsore, i) => ( +
1 && + sponsoredTrade.length - 1 !== i && + 'border-b' + }`} + > + + + 1inch - #1 DeFi aggregator +

{sponsore.title}

+
+
+

{sponsore.description}

+
+ ))} +
+ ); +}; + +export default Trade; diff --git a/apps/bos-components/src/includes/Common/QrCode.tsx b/apps/bos-components/src/includes/Common/QrCode.tsx new file mode 100644 index 000000000..ecc9f91ee --- /dev/null +++ b/apps/bos-components/src/includes/Common/QrCode.tsx @@ -0,0 +1,55 @@ +/** + * @interface Props + * @param {string} [value] - The data value to be encoded as a QR code (e.g., a URL, text, etc.). + * @param {number} [width] - The width of the QR code component. + * @param {number} [height] - The height of the QR code component. + */ +interface Props { + value: string; + width: number; + height: number; +} + +const QrCode = (props: Props) => { + const srcData = ` + + +
+ + + + + + `; + + return ( +
+