diff --git a/.storybook/main.js b/.storybook/main.js index 74afe16a..d650e381 100644 --- a/.storybook/main.js +++ b/.storybook/main.js @@ -1,34 +1,36 @@ module.exports = { - stories: ['../stories/**/*.stories.@(ts|tsx|js|jsx)'], - addons: ['@storybook/addon-links', '@storybook/addon-essentials', { - name: 'storybook-addon-sass-postcss', - options: { - loadSassAfterPostCSS: true, - postcssLoaderOptions: { - implementation: require('postcss') + stories: [ + '../stories/**/*.stories.@(ts|tsx|js|jsx)', + '../src/**/*.stories.@(ts|tsx|js|jsx)', + ], + addons: [ + '@storybook/addon-links', + '@storybook/addon-essentials', + { + name: 'storybook-addon-sass-postcss', + options: { + loadSassAfterPostCSS: true, + postcssLoaderOptions: { + implementation: require('postcss'), + }, + rule: { + test: /\.(scss|sass)$/i, + }, }, - rule: { - test: /\.(scss|sass)$/i - } - } - }, { - name: '@storybook/addon-postcss', - options: { - postcssLoaderOptions: { - implementation: require('postcss') - } - } - }, '@storybook/addon-mdx-gfm'], + }, + '@storybook/addon-mdx-gfm', + '@storybook/addon-styling', + ], // https://storybook.js.org/docs/react/configure/typescript#mainjs-configuration typescript: { - check: true // type-check stories during Storybook build + check: true, // type-check stories during Storybook build }, framework: { name: '@storybook/react-webpack5', - options: {} + options: {}, }, docs: { - autodocs: true - } -}; \ No newline at end of file + autodocs: true, + }, +}; diff --git a/package.json b/package.json index 6250980c..29a2651d 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ "dependencies": { "@acusti/react-code-input": "^3.11.0", "@babel/preset-typescript": "^7.21.4", + "@masa-finance/arcomia-contracts": "^1.4.2", "@masa-finance/masa-sdk": "^1.13.2", "@metamask/providers": "^10.2.1", "babel-loader": "^9.1.2", @@ -60,6 +61,7 @@ "@storybook/addon-links": "^7.0.2", "@storybook/addon-mdx-gfm": "^7.0.2", "@storybook/addon-postcss": "^2.0.0", + "@storybook/addon-styling": "^1.0.1", "@storybook/addons": "^7.0.2", "@storybook/react": "^7.0.2", "@storybook/react-webpack5": "^7.0.2", diff --git a/src/components/masa-interface/pages/gallery/add-sbt.tsx b/src/components/masa-interface/pages/gallery/add-sbt.tsx new file mode 100644 index 00000000..fb851809 --- /dev/null +++ b/src/components/masa-interface/pages/gallery/add-sbt.tsx @@ -0,0 +1,18 @@ +import { useLocalStorage } from '../../../../provider'; +import React, { useCallback, useState } from 'react'; +export const AddSBT = () => { + const { localStorageSet } = useLocalStorage(); + const [address, setAddress] = useState(''); + const [name, setName] = useState(''); + + const handleAddSBT = useCallback(() => { + localStorageSet(`masa-gallery-sbt-${name}`, { address, name }); + }, [address, setAddress, name, setName]); + return ( +
+ setAddress(e.target.value)} /> + setName(e.target.value)} /> + +
+ ); +}; diff --git a/src/components/masa-interface/pages/gallery/gallery.stories.tsx b/src/components/masa-interface/pages/gallery/gallery.stories.tsx new file mode 100644 index 00000000..902a1204 --- /dev/null +++ b/src/components/masa-interface/pages/gallery/gallery.stories.tsx @@ -0,0 +1,64 @@ +import React from 'react'; +import { MasaProvider } from '../../../../provider'; +import { Meta, StoryObj } from '@storybook/react'; +import { Gallery } from '.'; +import { GalleryItem } from './galleryItem'; + +const customRenderPokeSBT = { + name: 'PokeSBT', + address: '0xA5705C317367Ab3e17D0deACf530792745C29c10', + getMetadata: async function (sbt: { tokenId: string; tokenUri: string }) { + const apiUrl = sbt.tokenUri.replace('.json', ''); + const apiResponse = await fetch(apiUrl); + const data = await apiResponse.json(); + + return { + name: data.name, + image: data.sprites.front_default, + description: "", + }; + }, +}; +const meta: Meta = { + title: 'Gallery', + component: Gallery, + argTypes: {}, + decorators: [ + (Story) => ( + <> + +
+ +
+
+ + ), + ], + parameters: { + controls: { expanded: true }, + }, +}; + +export default meta; + +type Story = StoryObj; + +export const Primary: Story = { + render: () => , +}; + +export const Item: Story = { + render: () => ( + + ), +}; diff --git a/src/components/masa-interface/pages/gallery/gallery.tsx b/src/components/masa-interface/pages/gallery/gallery.tsx new file mode 100644 index 00000000..7baf327f --- /dev/null +++ b/src/components/masa-interface/pages/gallery/gallery.tsx @@ -0,0 +1,53 @@ +import { useMasa } from '../../../../provider'; +import React, { useEffect, useMemo, useState } from 'react'; +import { GalleryItem } from './galleryItem'; +import { ICreditScore, IGreen, SoulNameDetails } from '@masa-finance/masa-sdk'; +import { BigNumber } from 'ethers'; +import { Tabs } from './tabs'; + +export const types = { + Mint: [ + { name: 'to', type: 'address' }, + { name: 'authorityAddress', type: 'address' }, + { name: 'signatureDate', type: 'uint256' }, + ], +}; + +interface Greens { + tokenId: BigNumber; + tokenUri: string; + metadata?: IGreen | undefined; +} + +interface CreditScores { + tokenId: BigNumber; + tokenUri: string; + metadata?: ICreditScore | undefined; +} +export interface Tabs { + items: SoulNameDetails[] | Greens[] | CreditScores[]; + render: (SBT: any) => JSX.Element; + content: () => JSX.Element[]; + title: string; +} + +export interface CustomGallerySBT { + name: string; + address: string; + getMetadata: (item: { tokenId; tokenUri }) => Promise<{ + image: string; + name: string; + description: string; + }>; +} +export const Gallery = ({ setIndex, context }) => { + return ( +
+ setIndex('addSbt')} + /> +
+ ); +}; diff --git a/src/components/masa-interface/pages/gallery/galleryItem.tsx b/src/components/masa-interface/pages/gallery/galleryItem.tsx new file mode 100644 index 00000000..3593b820 --- /dev/null +++ b/src/components/masa-interface/pages/gallery/galleryItem.tsx @@ -0,0 +1,20 @@ +import React from 'react'; +export interface GalleryItemProps { + image: string; +} +export const GalleryItem = ({ image, title, description }) => { + return ( +
+ + + {(title || description) && ( +
+ {title &&

{title}

} + {description && ( +

{description}

+ )} +
+ )} +
+ ); +}; diff --git a/src/components/masa-interface/pages/gallery/index.tsx b/src/components/masa-interface/pages/gallery/index.tsx new file mode 100644 index 00000000..80dbd710 --- /dev/null +++ b/src/components/masa-interface/pages/gallery/index.tsx @@ -0,0 +1,193 @@ +import { useMasa } from '../../../../provider'; +import React, { useEffect, useMemo, useState } from 'react'; +import { InterfaceSubflow } from '../../interface-subflow'; +import { AddSBT } from './add-sbt'; +import { Gallery, Tabs } from './gallery'; +import { GalleryItem } from './galleryItem'; +function getLocalStorageRecordsByPrefix( + prefix: string +): { name: string; address: string }[] { + const records: any[] = []; + for (let i = 0; i < localStorage.length; i++) { + const key = localStorage.key(i); + if (key && key.startsWith(prefix)) { + records.push(JSON.parse(localStorage.getItem(key) ?? '')); + } + } + return records; +} + +const handleRender = (SBT: any) => { + const getMetadata = () => { + if (SBT.metadata) { + return SBT.metadata; + } else { + if (SBT.tokenId) { + return { + image: SBT.tokenUri, + }; + } + } + }; + + const metadata = getMetadata(); + return ( + + ); +}; + +const useCustomGallerySBT = (): any[] => { + const { customGallerySBT, masa } = useMasa(); + const [contracts, setContracts] = useState(); + + useEffect(() => { + (async () => { + if (customGallerySBT && customGallerySBT.length) { + const contracts: any[] = []; + for (let sbt of customGallerySBT) { + const sbtContract = await masa?.sbt.connect(sbt.address); + contracts.push({ ...sbtContract, ...sbt }); + } + setContracts(contracts); + } + })(); + }, [customGallerySBT, masa]); + + return contracts ?? []; +}; + +const useTabs = () => { + const savedSbtContracts = useSavedSbts('masa-gallery-sbt-'); + const savedBadgeContracts = useSavedSbts('masa-gallery-badge-'); + const customContracts = useCustomGallerySBT(); + + const [savedTabs, setSavedTabs] = useState(); + const [savedBadges, setSavedBadges] = useState(); + + useEffect(() => { + (async () => { + const contracts = [...customContracts, ...savedSbtContracts]; + const newTabs: any[] = []; + for (let contract of contracts) { + const tokens: any[] = await contract.list(); + const hidratatedTokens: any[] = []; + if (contract.getMetadata) { + for (let token of tokens) { + try { + const metadata = await contract.getMetadata(token); + hidratatedTokens.push({ metadata, ...token }); + } catch (e) { + console.log("METADTA ERROR", e) + } + } + } + newTabs.push({ + items: hidratatedTokens.length ? hidratatedTokens : tokens, + render: (item) => handleRender(item), + content: function () { + return this?.items?.map((item) => this.render(item)); + }, + title: contract.name, + }); + } + + setSavedTabs(newTabs); + })(); + }, [savedSbtContracts, customContracts]); + + useEffect(() => { + (async () => { + if (!savedBadgeContracts) return []; + const tokenList: any[] = []; + for (let contract of savedBadgeContracts) { + const tokens: any[] = await contract.list(); + tokenList.push(...tokens); + } + + setSavedBadges({ + items: tokenList ?? [], + render: (item) => handleRender(item), + content: function () { + //@ts-ignore + return this?.items?.map((item) => this?.render(item)); + }, + title: 'Badges', + }); + })(); + }, [savedBadgeContracts]); + + return { sbts: savedTabs, badges: savedBadges }; +}; +const useSavedSbts = (prefix): any[] => { + const { masa } = useMasa(); + + const [savedContracts, setSavedContracts] = useState(); + + const savedSBTs = useMemo(() => { + const sbts = getLocalStorageRecordsByPrefix(prefix); + return sbts; + }, [prefix]); + + useEffect(() => { + (async () => { + const contracts: any[] = []; + for (let sbt of savedSBTs) { + const sbtContract = await masa?.sbt.connect(sbt.address); + contracts.push({ ...sbtContract, ...sbt }); + } + setSavedContracts(contracts); + })(); + }, [savedSBTs, masa]); + return savedContracts ?? []; +}; + +const GalleryContainer = () => { + const pages = [Gallery]; + const { soulnames, greens, creditScores } = useMasa(); + const { sbts, badges } = useTabs(); + + const tabs: Tabs[] = [ + { + items: soulnames ?? [], + render: (item) => handleRender(item), + content: function () { + return this?.items?.map((item) => this.render(item)); + }, + title: 'Soulnames', + }, + { + items: greens ?? [], + render: (item) => handleRender(item), + content: function () { + return this?.items?.map((item) => this.render(item)); + }, + title: 'Masa Green', + }, + { + items: creditScores ?? [], + render: (item) => handleRender(item), + content: function () { + return this?.items?.map((item) => this.render(item)); + }, + title: 'Masa Credit Scores', + }, + badges ? badges : [], + ...(sbts ?? []), + ]; + + const context = { tabs }; + return ( + + ); +}; + +export { GalleryContainer as Gallery }; diff --git a/src/components/masa-interface/pages/gallery/tabs.tsx b/src/components/masa-interface/pages/gallery/tabs.tsx new file mode 100644 index 00000000..429077e9 --- /dev/null +++ b/src/components/masa-interface/pages/gallery/tabs.tsx @@ -0,0 +1,36 @@ +import React, { useState } from 'react'; + +const Tab = ({ title, active, onClick }) => ( +
  • + {title} +
  • +); + +export const Tabs = ({ tabs, wrapperClassName, onAdd }) => { + const [activeTab, setActiveTab] = useState(0); + + return ( +
    +
    +
    +
      + {tabs.map((tab, index) => ( + setActiveTab(index)} + /> + ))} +
    +
    +
    + + +
    +
    +
    + {tabs[activeTab].content()} +
    +
    + ); +}; diff --git a/src/components/masa-interface/pages/masa-green/code.tsx b/src/components/masa-interface/pages/masa-green/code.tsx index 41613a68..e0b96242 100644 --- a/src/components/masa-interface/pages/masa-green/code.tsx +++ b/src/components/masa-interface/pages/masa-green/code.tsx @@ -151,7 +151,7 @@ export const CodeInterface: React.FunctionComponent = ({

    Enter 2FA 6-digit code

    -

    {`We sent a code to your phone number ending in ${phoneNumber.slice( +

    {`We sent a code to your phone number ending in ${phoneNumber?.slice( -4 )}.`}

    diff --git a/src/components/masa-interface/pages/masa-green/index.tsx b/src/components/masa-interface/pages/masa-green/index.tsx index aa74ff5b..3ce18bdb 100644 --- a/src/components/masa-interface/pages/masa-green/index.tsx +++ b/src/components/masa-interface/pages/masa-green/index.tsx @@ -8,6 +8,7 @@ import { PhoneInputInterface } from './phone-input'; import { Success } from './success'; import { VerifyAndMintInterface } from './verifiy-and-mint'; +export interface MasaGreenProps {} const InterfaceMasaGreen = () => { const pages = [ AirdropPage, diff --git a/src/components/masa-interface/pages/masa-green/masa-green.stories.tsx b/src/components/masa-interface/pages/masa-green/masa-green.stories.tsx new file mode 100644 index 00000000..9459cccb --- /dev/null +++ b/src/components/masa-interface/pages/masa-green/masa-green.stories.tsx @@ -0,0 +1,79 @@ +import React from 'react'; +import { MasaProvider } from '../../../../provider'; +import { Meta, StoryObj } from '@storybook/react'; +import { ModalComponent } from '../../../modal'; +import InterfaceMasaGreen from '.'; +import { AirdropPage } from './airdrop'; +import { NotBotPage } from './not-a-bot'; +import { PhoneInputInterface } from './phone-input'; +import { CodeInterface } from './code'; +import { VerifyAndMintInterface } from './verifiy-and-mint'; +import { Success } from './success'; + +const meta: Meta = { + title: 'Masa Green', + component: InterfaceMasaGreen, + argTypes: {}, + decorators: [ + (Story) => ( +
    + {/* 👇 Decorators in Storybook also accept a function. Replace with Story() to enable it */} + +
    + ), + ], + parameters: { + controls: { expanded: true }, + }, +}; + +export default meta; + +type Story = StoryObj; + +const pagesParams = { + next: () => console.log('next'), + back: () => console.log('back'), + complete: () => console.log('complete'), + setIndex: () => console.log('setIndex'), + context: { + phoneNumber: '+1 234 567 890', + }, +}; + +export const Primary: Story = { + render: (props: any) => ( + + {}} setOpen={() => {}}> + + + + ), + args: { + open: false, + }, +}; + +export const Airdrop: Story = { + render: () => , +}; + +export const AntiBotDisclaimer: Story = { + render: () => , +}; + +export const PhoneInput: Story = { + render: () => , +}; + +export const CodeInput: Story = { + render: () => , +}; + +export const VerifyAndMint: Story = { + render: () => , +}; + +export const SuccessModal: Story = { + render: () => , +}; diff --git a/src/components/masa-interface/pages/masa-green/success.tsx b/src/components/masa-interface/pages/masa-green/success.tsx index 1cf80ea7..f08f566f 100644 --- a/src/components/masa-interface/pages/masa-green/success.tsx +++ b/src/components/masa-interface/pages/masa-green/success.tsx @@ -1,6 +1,7 @@ import { SubflowPage } from 'components/masa-interface/interface-subflow'; import { useMasa } from '../../../../provider'; import React from 'react'; + export const Success: React.FunctionComponent = ({ complete, }: SubflowPage) => { diff --git a/src/components/modal/styles.scss b/src/components/modal/styles.scss index 0092e2a8..792516ba 100644 --- a/src/components/modal/styles.scss +++ b/src/components/modal/styles.scss @@ -17,6 +17,15 @@ width: 100%; height: 100%; + &.story { + width: 100%; + + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; + } + .masa-modal-container { width: 100%; height: 100%; @@ -551,8 +560,140 @@ } } } -} + .masa-gallery-container { + display: flex; + flex-direction: column; + width: 100%; + .masa-gallery { + width: 100%; + display: grid; + grid-template-columns: repeat(3, 1fr); + grid-gap: 20px; + + .gallery-item { + padding: 12px 18px; + background: rgba(0, 0, 0, 1); + border-radius: 8px; + box-sizing: border-box; + transition: background-color 300ms; + + max-width: 300px; + + display: flex; + flex-direction: column; + align-items: center; + &:hover { + background: rgba(3, 1, 25, 0.9); + } + + img { + width: 100%; + max-width: 280px; + border-radius: 12px; + } + + .gallery-item-info { + padding: 16px 0; + font-size: 21px; + font-family: Inter; + font-weight: 500; + color: white; + + width: 100%; + + display: flex; + flex-direction: column; + gap: 8px; + + .gallery-item-title { + margin: 0; + word-wrap: break-word; + font-size: 18px; + } + + .gallery-item-description { + margin: 0; + } + } + } + } + } + + .tabs-container { + width: 100%; + display: flex; + flex-direction: column; + } + .tabs-header { + width: 100%; + display: flex; + flex-direction: row; + align-items: center; + } + .tabs-wrapper { + display: flex; + flex-direction: row; + flex-grow: 1; + } + .tabs { + display: flex; + list-style-type: none; + padding: 0; + margin-bottom: 16px; + position: relative; + } + + .tab-content { + width: 100%; + } + .tab { + padding: 8px 16px; + font-size: 16px; + cursor: pointer; + position: relative; + transition: color 0.3s ease; + font-family: Ezra, 'Helvetica Neue'; + + &:hover { + color: black; + } + } + + .active { + color: black; + } + + .active::before { + content: ''; + position: absolute; + bottom: -4px; + left: 0; + width: 100%; + height: 2px; + background-color: black; + transition: transform 0.3s ease; + } + + .plus-button { + display: flex; + justify-content: center; + align-items: center; + margin-left: 8px; + font-size: 24px; + width: 32px; + height: 32px; + cursor: pointer; + border: 1px solid #ccc; + border-radius: 50%; + transition: background-color 0.3s ease, color 0.3s ease; + + &:hover { + background-color: black; + color: #fff; + } + } +} // RODAL STYLES /* -- container -- */ .rodal, diff --git a/src/provider/masa-context-provider.tsx b/src/provider/masa-context-provider.tsx index bf7c6bde..3f81e36a 100644 --- a/src/provider/masa-context-provider.tsx +++ b/src/provider/masa-context-provider.tsx @@ -20,6 +20,7 @@ import { Signer, Wallet } from 'ethers'; import { MasaContext } from './masa-context'; import { MasaShape } from './masa-shape'; import { useScopes } from './modules/scopes/scopes'; +import { CustomGallerySBT } from 'components/masa-interface/pages/gallery/gallery'; export { SoulNameErrorCodes }; @@ -37,6 +38,7 @@ export interface MasaContextProviderProps extends MasaShape { signer?: Wallet | Signer; environmentName?: EnvironmentNameEx; arweaveConfig?: ArweaveConfig; + customGallerySBT?: CustomGallerySBT[]; } export const MasaContextProvider = ({ @@ -55,6 +57,8 @@ export const MasaContextProvider = ({ verbose = false, // force specific network forceNetwork, + // Custom SBT render for gallery + customGallerySBT, }: MasaContextProviderProps): JSX.Element => { // masa const [masaInstance, setMasaInstance] = useState(); @@ -125,6 +129,7 @@ export const MasaContextProvider = ({ openMintSoulnameModal, openMintMasaGreen, useModalSize, + openGallery, modalSize, } = useModal(isLoggedIn, hasWalletAddress, areScopesFullfiled); @@ -231,6 +236,7 @@ export const MasaContextProvider = ({ openMintSoulnameModal, openMintMasaGreen, useModalSize, + openGallery, modalSize, // wallet @@ -274,6 +280,10 @@ export const MasaContextProvider = ({ SupportedNetworks, switchNetwork, forceNetwork, + + // gallery + customGallerySBT, + }; return ( diff --git a/src/provider/masa-shape.ts b/src/provider/masa-shape.ts index cb94ff9e..2d320bfa 100644 --- a/src/provider/masa-shape.ts +++ b/src/provider/masa-shape.ts @@ -11,6 +11,7 @@ import { VerifyGreenResult, } from '@masa-finance/masa-sdk'; import { BigNumber, Signer, Wallet } from 'ethers'; +import { CustomGallerySBT } from 'components/masa-interface/pages/gallery/gallery'; export interface MasaShape { children?: React.ReactNode; @@ -45,7 +46,8 @@ export interface MasaShape { openMintMasaGreen?: (callback?: () => void) => void; modalSize?: { width: number; height: number } | null; useModalSize?: (size: { width: number; height: number }) => void; - + openGallery?: (callback?: () => void) => void; + // wallet walletAddress?: string; isWalletLoading?: boolean; @@ -107,4 +109,7 @@ export interface MasaShape { SupportedNetworks?: Partial<{ [index in NetworkName]: Network }>; switchNetwork?: (networkName: NetworkName) => void; forceNetwork?: NetworkName; + + // gallery + customGallerySBT?: CustomGallerySBT[] } diff --git a/src/provider/modules/modal/modal.ts b/src/provider/modules/modal/modal.ts index bcc79faf..5c7d7f87 100644 --- a/src/provider/modules/modal/modal.ts +++ b/src/provider/modules/modal/modal.ts @@ -19,6 +19,7 @@ export const useModal = ( } | null; setModalSize: (size: { width: number; height: number }) => void; useModalSize: (size: { width: number; height: number }) => void; + openGallery: (callback?: () => void) => void; } => { const [isModalOpen, setModalOpen] = useState(false); const [modalCallback, setModalCallback] = useState<(() => void) | null>(null); @@ -89,6 +90,20 @@ export const useModal = ( [setForcedPage, setModalOpen, setModalCallback] ); + const openGallery = useCallback( + (mintCallback?: () => void) => { + setForcedPage?.('gallery'); + setModalOpen(true); + const cb = () => { + setForcedPage?.(null); + if (mintCallback) mintCallback(); + }; + + setModalCallback(() => cb); + }, + [setForcedPage, setModalOpen, setModalCallback] + ); + return { isModalOpen, closeModal, @@ -101,5 +116,6 @@ export const useModal = ( modalSize, setModalSize, useModalSize, + openGallery, }; }; diff --git a/stories/masa.stories.tsx b/stories/masa.stories.tsx index 8428fc8a..eddd6e9b 100644 --- a/stories/masa.stories.tsx +++ b/stories/masa.stories.tsx @@ -34,7 +34,7 @@ const Component = (): JSX.Element => { const handleConnect = useCallback(() => { connect?.({ - scope: ['auth', 'soulname', 'identity'], + scope: ['auth'], callback: function () { alert('hello hello connected'); }, @@ -104,7 +104,7 @@ const Component = (): JSX.Element => { const Template: Story = (props: Args) => { return ( <> - + @@ -122,7 +122,7 @@ Default.args = {}; const MasaGreenTemplate: Story = (props: Args) => { return ( <> - + { diff --git a/yarn.lock b/yarn.lock index a42b7c59..3427e8c5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2217,6 +2217,13 @@ resolved "https://registry.yarnpkg.com/@juggle/resize-observer/-/resize-observer-3.4.0.tgz#08d6c5e20cf7e4cc02fd181c4b0c225cd31dbb60" integrity sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA== +"@masa-finance/arcomia-contracts@^1.4.2": + version "1.4.2" + resolved "https://registry.yarnpkg.com/@masa-finance/arcomia-contracts/-/arcomia-contracts-1.4.2.tgz#a62c7ce1c8fe689dc7f4dd726d9a46afb3551d21" + integrity sha512-aLCRjWkto5b8qOJmYxTv5LLLaz7Hvk+irO2j35jsuUjdycJy0CX77WLmdFUDx7DCR7HQZgLlSNVJVEMt4urWeg== + dependencies: + ethers "~5.7.2" + "@masa-finance/masa-contracts-identity@^1.5.2": version "1.5.2" resolved "https://registry.yarnpkg.com/@masa-finance/masa-contracts-identity/-/masa-contracts-identity-1.5.2.tgz#b39369c0be306d8c21d85ae432c1c4c037e8ad10" @@ -2775,6 +2782,24 @@ postcss-loader "^4.2.0" style-loader "^1.3.0" +"@storybook/addon-styling@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@storybook/addon-styling/-/addon-styling-1.0.1.tgz#c68268a4e7ee993b5f595a0f40c9ba907a44fb2c" + integrity sha512-ERi52/Rebk3HPQAA0Xnhd5Opl3Q4csX1yYkYKRa5vAKTKIX7n3YT6I5V5zasCdNHT5+LkJ5ZUJb4AQ5T/QPYRw== + dependencies: + "@storybook/api" "^7.0.2" + "@storybook/components" "^7.0.2" + "@storybook/core-events" "^7.0.2" + "@storybook/manager-api" "^7.0.2" + "@storybook/preview-api" "^7.0.2" + "@storybook/theming" "^7.0.2" + "@storybook/types" "^7.0.2" + css-loader "^6.7.3" + postcss-loader "^7.2.4" + resolve-url-loader "^5.0.0" + sass-loader "^13.2.2" + style-loader "^3.3.2" + "@storybook/addon-toolbars@7.0.2": version "7.0.2" resolved "https://registry.yarnpkg.com/@storybook/addon-toolbars/-/addon-toolbars-7.0.2.tgz#bc883c60cb979bac4e84b1b1b4757552d1e6c384" @@ -2857,6 +2882,14 @@ "@storybook/client-logger" "7.0.2" "@storybook/manager-api" "7.0.2" +"@storybook/api@^7.0.2": + version "7.0.5" + resolved "https://registry.yarnpkg.com/@storybook/api/-/api-7.0.5.tgz#e4f01d0f68d94082f2328bd188d198718c4e7486" + integrity sha512-0YftXdLOLPKnMtBxJrCitrG5BZUYUMs1KmFcjlLzLVbj+KOybvX1cTBkWPuoFY2YRS1FA79gHsth1Ed9oO3k1A== + dependencies: + "@storybook/client-logger" "7.0.5" + "@storybook/manager-api" "7.0.5" + "@storybook/blocks@7.0.2": version "7.0.2" resolved "https://registry.yarnpkg.com/@storybook/blocks/-/blocks-7.0.2.tgz#b4bdcb9ca48d89804dd5ad939abc3b0c2df73e35" @@ -2968,6 +3001,18 @@ qs "^6.10.0" telejson "^7.0.3" +"@storybook/channel-postmessage@7.0.5": + version "7.0.5" + resolved "https://registry.yarnpkg.com/@storybook/channel-postmessage/-/channel-postmessage-7.0.5.tgz#87edc33664e6c612c4f830d54d9c99f368d2483c" + integrity sha512-Ri0188tHfvg2asdNOVUeLU1w1G/V485y/vatZ/vC3My9cG8P39t8ZKAJdA3hukc+7RZKZU+snqCz7de89/CF7Q== + dependencies: + "@storybook/channels" "7.0.5" + "@storybook/client-logger" "7.0.5" + "@storybook/core-events" "7.0.5" + "@storybook/global" "^5.0.0" + qs "^6.10.0" + telejson "^7.0.3" + "@storybook/channel-websocket@7.0.2": version "7.0.2" resolved "https://registry.yarnpkg.com/@storybook/channel-websocket/-/channel-websocket-7.0.2.tgz#f9dacfe4eebc840bdd5d491749a0be0ad35ff12c" @@ -2990,6 +3035,11 @@ resolved "https://registry.yarnpkg.com/@storybook/channels/-/channels-7.0.2.tgz#2eb124d14fff50d4686888dca88f130c5aee358d" integrity sha512-qkI8mFy9c8mxN2f01etayKhCaauL6RAsxRzbX1/pKj6UqhHWqqUbtHwymrv4hG5qDYjV1e9pd7ae5eNF8Kui0g== +"@storybook/channels@7.0.5": + version "7.0.5" + resolved "https://registry.yarnpkg.com/@storybook/channels/-/channels-7.0.5.tgz#b7dbc11e658a5e6a694bd7df2a0514c3b27ba318" + integrity sha512-WiSPXgOK63jAlDDmbTs1sVXoYe3r/4VjpfwhEcxSPU544YQVARF1ePtiGjlp8HVFhZh1Q7afbVGJ9w96++u98A== + "@storybook/cli@7.0.2": version "7.0.2" resolved "https://registry.yarnpkg.com/@storybook/cli/-/cli-7.0.2.tgz#f96c42e7660b8f8f14595483036b3b5ef6724dc9" @@ -3056,6 +3106,13 @@ dependencies: "@storybook/global" "^5.0.0" +"@storybook/client-logger@7.0.5": + version "7.0.5" + resolved "https://registry.yarnpkg.com/@storybook/client-logger/-/client-logger-7.0.5.tgz#9655534a88bd61a3824024dd960d2d82bcaeaded" + integrity sha512-p8Vtb5G/l3gePNDbNjqgGsikthRqDfsPAqFEsAvBWJVZ3vq/ZSU4IsCWSLO/kdkyJyhTXMqQZnOpQ0pDXlOPcQ== + dependencies: + "@storybook/global" "^5.0.0" + "@storybook/codemod@7.0.2": version "7.0.2" resolved "https://registry.yarnpkg.com/@storybook/codemod/-/codemod-7.0.2.tgz#a1735d8b6448569b36d7787b08ba0c5dcc6ad952" @@ -3116,6 +3173,20 @@ use-resize-observer "^9.1.0" util-deprecate "^1.0.2" +"@storybook/components@^7.0.2": + version "7.0.5" + resolved "https://registry.yarnpkg.com/@storybook/components/-/components-7.0.5.tgz#892f35c19b8dfa88477aad6df4523ba6763b1366" + integrity sha512-SHftxNH3FG3RZwJ5nbyBZwn5pkI3Ei2xjD7zDwxztI8bCp5hPnOTDwAnQZZCkeW7atSQUe7xFkYqlCgNmXR4PQ== + dependencies: + "@storybook/client-logger" "7.0.5" + "@storybook/csf" "^0.1.0" + "@storybook/global" "^5.0.0" + "@storybook/theming" "7.0.5" + "@storybook/types" "7.0.5" + memoizerific "^1.11.3" + use-resize-observer "^9.1.0" + util-deprecate "^1.0.2" + "@storybook/core-client@7.0.2": version "7.0.2" resolved "https://registry.yarnpkg.com/@storybook/core-client/-/core-client-7.0.2.tgz#91112c7904a709ea4204e131a4f36e3c25872c8c" @@ -3161,6 +3232,11 @@ resolved "https://registry.yarnpkg.com/@storybook/core-events/-/core-events-7.0.2.tgz#5038aa5ea1e035099ed1dc48aa233e232ff882e7" integrity sha512-1DCHCwHRL3+rlvnVVc/BCfReP31XaT2WYgcLeGTmkX1E43Po1MkgcM7PnJPSaa9POvSqZ+6YLZv5Bs1SXbufow== +"@storybook/core-events@7.0.5", "@storybook/core-events@^7.0.2": + version "7.0.5" + resolved "https://registry.yarnpkg.com/@storybook/core-events/-/core-events-7.0.5.tgz#d92490df43f3bc28bf05b3d9a69ae153aca94ecd" + integrity sha512-bYQFZlJR3n5gFk5GVIemuL3m6aYPF6DVnzj6n9UcMZDlHcOZ2B2WbTmAUrGy0bmtj/Fd6ZJKDpBhh3cRRsYkbA== + "@storybook/core-server@7.0.2": version "7.0.2" resolved "https://registry.yarnpkg.com/@storybook/core-server/-/core-server-7.0.2.tgz#23f14803c8d141f6af2cffdb240831c6f69ee7e3" @@ -3301,6 +3377,27 @@ telejson "^7.0.3" ts-dedent "^2.0.0" +"@storybook/manager-api@7.0.5", "@storybook/manager-api@^7.0.2": + version "7.0.5" + resolved "https://registry.yarnpkg.com/@storybook/manager-api/-/manager-api-7.0.5.tgz#73292e9d8c4c4ef0c06effe5fe1b6737a01c7f69" + integrity sha512-zZR5uL3vR5skNge0a8FZNZfnGuDYVLVBpNVi5/UpnVRA/Pr439NHXaJL8xzdT7Xcvs+qp1FHShMM4gZVIFHrKA== + dependencies: + "@storybook/channels" "7.0.5" + "@storybook/client-logger" "7.0.5" + "@storybook/core-events" "7.0.5" + "@storybook/csf" "^0.1.0" + "@storybook/global" "^5.0.0" + "@storybook/router" "7.0.5" + "@storybook/theming" "7.0.5" + "@storybook/types" "7.0.5" + dequal "^2.0.2" + lodash "^4.17.21" + memoizerific "^1.11.3" + semver "^7.3.7" + store2 "^2.14.2" + telejson "^7.0.3" + ts-dedent "^2.0.0" + "@storybook/manager@7.0.2": version "7.0.2" resolved "https://registry.yarnpkg.com/@storybook/manager/-/manager-7.0.2.tgz#1060afdc5bb4b69252d1ed1ad4d5e01d6a355b95" @@ -3390,6 +3487,27 @@ ts-dedent "^2.0.0" util-deprecate "^1.0.2" +"@storybook/preview-api@^7.0.2": + version "7.0.5" + resolved "https://registry.yarnpkg.com/@storybook/preview-api/-/preview-api-7.0.5.tgz#7b664d1f99a374df06da1c45e6d2a54b6ebff64e" + integrity sha512-mZruATt5JXfLuXJfOo30WCXILXjK+hs0HwtUDGRVW/J4Ql8CdNPB+WF56ZgeWUnMAYRf392bN3uNwmZx4v4Fog== + dependencies: + "@storybook/channel-postmessage" "7.0.5" + "@storybook/channels" "7.0.5" + "@storybook/client-logger" "7.0.5" + "@storybook/core-events" "7.0.5" + "@storybook/csf" "^0.1.0" + "@storybook/global" "^5.0.0" + "@storybook/types" "7.0.5" + "@types/qs" "^6.9.5" + dequal "^2.0.2" + lodash "^4.17.21" + memoizerific "^1.11.3" + qs "^6.10.0" + synchronous-promise "^2.0.15" + ts-dedent "^2.0.0" + util-deprecate "^1.0.2" + "@storybook/preview@7.0.2": version "7.0.2" resolved "https://registry.yarnpkg.com/@storybook/preview/-/preview-7.0.2.tgz#f48f2a4383f5f8e0a9695c920b88c765b29549ae" @@ -3474,6 +3592,15 @@ memoizerific "^1.11.3" qs "^6.10.0" +"@storybook/router@7.0.5": + version "7.0.5" + resolved "https://registry.yarnpkg.com/@storybook/router/-/router-7.0.5.tgz#d89f1911b555a7c2fdcdfcc35947ecdc1b18b7d7" + integrity sha512-tvbSb+G3Ft5Z7McwUcMa13D8pM4pdoCu/pKCVMOlAI5TZF3lidLMq2RCsrztpHiYBrhZcp6dWfErosXa+BYvwQ== + dependencies: + "@storybook/client-logger" "7.0.5" + memoizerific "^1.11.3" + qs "^6.10.0" + "@storybook/store@7.0.2": version "7.0.2" resolved "https://registry.yarnpkg.com/@storybook/store/-/store-7.0.2.tgz#d406027f4edcc7907d9f13df153aa13cd81898cc" @@ -3525,6 +3652,16 @@ "@storybook/global" "^5.0.0" memoizerific "^1.11.3" +"@storybook/theming@7.0.5", "@storybook/theming@^7.0.2": + version "7.0.5" + resolved "https://registry.yarnpkg.com/@storybook/theming/-/theming-7.0.5.tgz#29b88074c73947a801be10f0b5d8c34220dd240f" + integrity sha512-XgQXKktcVBOkJT5gXjqtjH7C2pjdreDy0BTVTaEmFzggyyw+cgFrkJ7tuB27oKwYe+svx26c/olVMSHYf+KqhA== + dependencies: + "@emotion/use-insertion-effect-with-fallbacks" "^1.0.0" + "@storybook/client-logger" "7.0.5" + "@storybook/global" "^5.0.0" + memoizerific "^1.11.3" + "@storybook/types@7.0.2": version "7.0.2" resolved "https://registry.yarnpkg.com/@storybook/types/-/types-7.0.2.tgz#32ae7b9521d42617bd8fb87f3b85b0f77d2739f5" @@ -3535,6 +3672,16 @@ "@types/express" "^4.7.0" file-system-cache "^2.0.0" +"@storybook/types@7.0.5", "@storybook/types@^7.0.2": + version "7.0.5" + resolved "https://registry.yarnpkg.com/@storybook/types/-/types-7.0.5.tgz#d8a3a5aa2dc33f7b81df2833e09d3eaa2f6c9c3c" + integrity sha512-By+tF3B30QiCnzEJ+Z73M2usSCqBWEmX4OGT1KbiEzWekkrsfCfpZwfzeMw1WwdQGlB1gLKTzB8wZ1zZB8oPtQ== + dependencies: + "@storybook/channels" "7.0.5" + "@types/babel__core" "^7.0.0" + "@types/express" "^4.7.0" + file-system-cache "^2.0.0" + "@tootallnate/once@1": version "1.1.2" resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" @@ -4365,6 +4512,14 @@ address@^1.0.1: resolved "https://registry.yarnpkg.com/address/-/address-1.2.2.tgz#2b5248dac5485a6390532c6a517fda2e3faac89e" integrity sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA== +adjust-sourcemap-loader@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/adjust-sourcemap-loader/-/adjust-sourcemap-loader-4.0.0.tgz#fc4a0fd080f7d10471f30a7320f25560ade28c99" + integrity sha512-OXwN5b9pCUXNQHJpwwD2qP40byEmSgzj8B4ydSN0uMNYWiFmJ6x6KwUllMmfk8Rwu/HJDFR7U8ubsWBoN0Xp0A== + dependencies: + loader-utils "^2.0.0" + regex-parser "^2.2.11" + aes-js@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" @@ -5658,6 +5813,11 @@ core-util-is@~1.0.0: resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== +cosmiconfig-typescript-loader@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-4.3.0.tgz#c4259ce474c9df0f32274ed162c0447c951ef073" + integrity sha512-NTxV1MFfZDLPiBMjxbHRwSh5LaLcPMwNdCutmnHJCKoVnlvldPWlllonKwrsRJ5pYZBIBGRWWU2tfvzxgeSW5Q== + cosmiconfig@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-6.0.0.tgz#da4fee853c52f6b1e6935f41c1a2fc50bd4a9982" @@ -5690,6 +5850,16 @@ cosmiconfig@^8.0.0: parse-json "^5.0.0" path-type "^4.0.0" +cosmiconfig@^8.1.3: + version "8.1.3" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-8.1.3.tgz#0e614a118fcc2d9e5afc2f87d53cd09931015689" + integrity sha512-/UkO2JKI18b5jVMJUp0lvKFMpa/Gye+ZgZjKD+DGEN9y7NRcf/nK1A0sp67ONmKtnDCNMS44E6jrk0Yc3bDuUw== + dependencies: + import-fresh "^3.2.1" + js-yaml "^4.1.0" + parse-json "^5.0.0" + path-type "^4.0.0" + country-flag-icons@^1.5.4: version "1.5.7" resolved "https://registry.yarnpkg.com/country-flag-icons/-/country-flag-icons-1.5.7.tgz#f1f2ddf14f3cbf01cba6746374aeba94db35d4b4" @@ -10024,7 +10194,7 @@ nano-time@1.0.0: dependencies: big-integer "^1.6.16" -nanoid@^3.3.1: +nanoid@^3.3.1, nanoid@^3.3.6: version "3.3.6" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.6.tgz#443380c856d6e9f9824267d960b4236ad583ea4c" integrity sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA== @@ -10699,6 +10869,16 @@ postcss-loader@^7.1.0: klona "^2.0.6" semver "^7.3.8" +postcss-loader@^7.2.4: + version "7.2.4" + resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-7.2.4.tgz#2884f4ca172de633b2cf1f93dc852968f0632ba9" + integrity sha512-F88rpxxNspo5hatIc+orYwZDtHFaVFOSIVAx+fBfJC1GmhWbVmPWtmg2gXKE1OxJbneOSGn8PWdIwsZFcruS+w== + dependencies: + cosmiconfig "^8.1.3" + cosmiconfig-typescript-loader "^4.3.0" + klona "^2.0.6" + semver "^7.3.8" + postcss-merge-longhand@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-6.0.0.tgz#6f627b27db939bce316eaa97e22400267e798d69" @@ -10931,6 +11111,15 @@ postcss@^7.0.14, postcss@^7.0.32, postcss@^7.0.35, postcss@^7.0.5, postcss@^7.0. picocolors "^0.2.1" source-map "^0.6.1" +postcss@^8.2.14: + version "8.4.22" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.22.tgz#c29e6776b60ab3af602d4b513d5bd2ff9aa85dc1" + integrity sha512-XseknLAfRHzVWjCEtdviapiBtfLdgyzExD50Rg2ePaucEesyh8Wv4VPdW0nbyDa1ydbrAxV19jvMT4+LFmcNUA== + dependencies: + nanoid "^3.3.6" + picocolors "^1.0.0" + source-map-js "^1.0.2" + postcss@^8.4.19, postcss@^8.4.21: version "8.4.21" resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.21.tgz#c639b719a57efc3187b13a1d765675485f4134f4" @@ -11540,6 +11729,11 @@ regenerator-transform@^0.15.1: dependencies: "@babel/runtime" "^7.8.4" +regex-parser@^2.2.11: + version "2.2.11" + resolved "https://registry.yarnpkg.com/regex-parser/-/regex-parser-2.2.11.tgz#3b37ec9049e19479806e878cabe7c1ca83ccfe58" + integrity sha512-jbD/FT0+9MBU2XAZluI7w2OBs1RBi6p9M83nkoZayQXXU9e8Robt69FcZc7wU4eJD/YFTjn1JdCk3rbMJajz8Q== + regexp.prototype.flags@^1.2.0, regexp.prototype.flags@^1.4.3: version "1.4.3" resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz#87cab30f80f66660181a3bb7bf5981a872b367ac" @@ -11651,6 +11845,17 @@ resolve-from@^5.0.0: resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== +resolve-url-loader@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/resolve-url-loader/-/resolve-url-loader-5.0.0.tgz#ee3142fb1f1e0d9db9524d539cfa166e9314f795" + integrity sha512-uZtduh8/8srhBoMx//5bwqjQ+rfYOUq8zC9NrMUGtjBiGTtFJM42s58/36+hTqeqINcnYe08Nj3LkK9lW4N8Xg== + dependencies: + adjust-sourcemap-loader "^4.0.0" + convert-source-map "^1.7.0" + loader-utils "^2.0.0" + postcss "^8.2.14" + source-map "0.6.1" + resolve.exports@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-2.0.0.tgz#c1a0028c2d166ec2fbf7d0644584927e76e7400e" @@ -12120,16 +12325,16 @@ source-map-support@^0.5.16, source-map-support@~0.5.20: buffer-from "^1.0.0" source-map "^0.6.0" +source-map@0.6.1, source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + source-map@^0.5.7: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ== -source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== - source-map@^0.7.3: version "0.7.4" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.4.tgz#a9bbe705c9d8846f4e08ff6765acf0f1b0898656"