npm package: @mojito-inc/mixers
Description: 🍸 React components for the Mojito Platform, Reference App and third-party projects.
Latest version: 1.0.3-beta.20

<br />


<h1 align="center">🍸 Mojito Mixers</h1>

<br /><br />


<p align="center">
  👨‍💻 React components for the Mojito Platform, Reference App and third-party projects, including Mojito's Checkout / Payment UI  and payment sandbox / test app to easily test credit card, ACH, Wire and Crypto payments with Circle, 3DS, Plaid, Vertex and TaxJar integrations.
</p><p align="center">
  🚀 Check it out at <a href="https://payments-staging.mojito.xyz/" target="_blank">https://payments-staging.mojito.xyz/</a>!
</p>

<br />


<p align="center">
  <a href="https://www.npmjs.com/package/@mojito-inc/mixers" target="_blank">
    <img src="https://img.shields.io/npm/v/@mojito-inc/mixers?color=%23CC3534&style=for-the-badge" />
  </a>
</p>

<br />


<p align="center">
  <a href="https://payments-staging.mojito.xyz/" target="_blank">
    <img src="./screenshots/checkout.png" width="1200" />
  </a>
</p>

<br />

[Mixer v1 to Mixer v2 Migration](./MixerV2Migration.md)


## Using this library in your project Mixer v2

You can install this project with one of these commands:

    npm install --save @mojito-inc/mixers
    yarn add @mojito-inc/mixers

Alternatively, once you've built the library using `yarn build`, you can install it locally in another project adding
this line to your `package.json`'s dependencies. If you update it, make sure you remove the entry from `yarn.lock` and
re-install it.

    "@mojito-inc/mixers": "file:../mojito-mixers"

Also, make sure you install the following dependencies:

    react
    react-dom
    @mui/material

And also, keep in mind:

- `@emotion/react` is not needed.

- `@emotion/styled` is needed as stated in [MUI's docs](https://mui.com/guides/interoperability/):

    > Keep `@emotion/styled` as a dependency of your project. Even if you never use it explicitly, it's a peer dependency of `@mui/material`.

- `styled-components` is needed as stated in [`react-payment-inputs`' docs](https://github.com/medipass/react-payment-inputs#using-the-built-in-styled-wrapper), but it's not used:

    > Note: <PaymentInputsWrapper> requires styled-components to be installed as a dependency.
    >
    > By default, React Payment Inputs does not have built-in styling for it's inputs. However, React Payment Inputs comes with a styled wrapper which combines the card number, expiry & CVC fields...

<br />


## Usage:

Fist, you need to create a `CheckoutComponent: React.FC<PUICheckoutProps>` component that renders `MojitoCheckout`
and passes it all required props. Simply copy the following file and adapt it to your needs:

You can find an example here: [app/src/layout/CheckoutLayout.tsx](./app/src/layout/CheckoutLayout.tsx).

You'll use this `CheckoutComponent` component in your code instead of `MojitoCheckout` just so that you don't have to
repeat properties that rarely change, like the theme  [DefaultThemes](#theme)

## Note:

In the `_app.tsx` file, please add the following line: `<Script src="https://cdn.checkout.com/js/framesv2.min.js" />`. if it was not added, credit card payments won't work.
<br />

### If you are using create-react-app

Add below packages as dependencies in your package.json

```
{
  ...
  "dependencies": {
    ...
    "url": "latest",
    "http": "npm:http-browserify",
    "https": "npm:https-browserify",
    "zlib": "npm:browserify-zlib",
    "http-browserify": "latest",
    "https-browserify": "latest",
    "browserify-zlib": "latest",
    "assert": "^2.0.0",
    "stream": "^0.0.2"
  }
}
```

To ignore the sourcemap warnings, create a .env file with the following in your root directory:

```
GENERATE_SOURCEMAP=false
```

```
import { MojitoCheckout } from '@mojito-inc/mixers';

  const theme = {
            font: {
              primary: 'Sneak',
              secondary: 'Sneak',
            },
            color: {
              primary: '#6663FD',
              secondary: '#FFFFFF',
              background: '#FAFAFC',
              errorBackground: '#FEE3E5',
              text: '#000000',
              cardBackground: '#FFFFFF',
              checkout: {
                continueButtonBackground: '#6663FD',
                continueButtonTextColor: '#FFFFFF',
                disableButtonBackground: '#DADAE9',
              },
              placeholder: '#BABEC5',
              costBreakdown: {
                applyButtonBackground: '#DADAE9',
                applyButtonTextColor: '#FFFFFF',
              },
              paymentConfirmation: {
                awaitingPaymentBackground: '#f0ebeb',
                awaitingPaymentTextColor: 'orange',
                processedBackground: '#E5F9E0',
                processedTextColor: '#000000',
                copyIconColor: '#042439',
              },
              highlightedText: '#6663FD',
              unHighlightedText: '#6663FB',
              errorText: '',
              linksText: '',
              multiSigBackground: '',
              multiSigBorder: '',
              multiSigText: '',
            },
          };

  const handleClickGoToMarketPlace = useCallback(async () => {
  }, []);

  const onEvent = (e:string)=>{
    console.log("EVENT",e)
  }

  const paymentInstructions = (paymentId: string) => {
    return (
      <>
        <Typography fontWeight="500" fontSize="20px" marginBottom="8px">
          Thank you for your purchase! The order is on its way to you.
        </Typography>
        <Typography
          fontSize="16px"
          variant="body1"
          color="#8A8AB9">
          Order #: { paymentId }
        </Typography>
        <Typography marginTop="16px" variant="body2">
          We have received your payment. Once everything is confirmed, we will send an email with your order confirmation.
          <br />
          <br />
          If you choose to store your NFT in a wallet, you can view it on the respective wallet page.
          <br />
          <br />
          If you selected to have it sent to an email wallet, you should find it by logging into <a href="https://ews.thirdweb.com/">https://ews.thirdweb.com/</a>.
        </Typography>
      </>
    );
  };

  
  <MojitoCheckout
    uri={ API_URL }
    userInfo: {
      email: user?.email,
    },
    checkoutOptions={{
      orgId: 'd086ea16-d40d-454c-84a4-64b5e940670a',
      lotId: '17cd1000-323d-4a20-8e5f-7a8598ffae2a',
      quantity: 1,
      collectionItemId: '64e99437-ac2e-45bc-b4a6-4750985b4e81',
      discountCode: '',
      invoiceId: '',
    }}
    theme={ theme }
    events={
      onEvent:onEvent,
      onCatch:onCatch,
      onError:onError,
    }
    walletDetails={{
      wallet: {
        account: walletAddress,
        chainId: chainId,
        connected: true,
        balance: currencyBalance,
        providerType: 'Metamask',
      }, // Pass custom connected wallet details 
      saveWalletData: saveWalletData, // In the function callback you will get a wallet details
      onDisconnect: onDisconnect, // To handle custom disconnect connect wallet
      onClickRefetchBalance: onClickRefetchBalance, // To handle custom refetch balance
    }}
    onClickConnectWallet={ onClickConnectWallet } // To handle custom connect wallet component
    uiConfiguration={
      global:{
        logoSrc: require('./logo.svg),
        loaderImageSrc: require('./loading.svg),
        errorImageSrc: require('./error.svg),
      }
      payment: {
        creditCard: true,
        walletConnect: true,
        wire: true,
        coinbase: true
      },
      costBreakdown: {
        showDiscountCode: true
      },
      paymentConfirmation: {
        onGoTo: () => handleClickGoToMarketPlace(),
        creditCardInstructions: paymentInstructions //Your own instructions for credit card,
        metamaskInstructions: paymentInstructions //Your own instructions for metamask,
        wireTransferInstructions: paymentInstructions //Your own instructions for wire transfer,
      },
      delivery: {
        creditCard: {
          enableMultiSig: false,
          apiKey: configuration.PAYMENT_API_KEY,
        },
      },
      walletConnect: {
        orgId: configuration.ORGANIZATION_ID,
        walletConnectProjectId: configuration.PROJECT_ID,
        paperClientId: configuration.PAPER_CLIENT_ID,
        clientId: configuration.clientId,
        activeChain: configuration.activeChain,
        isPaperWallet: false, // if true it will work as paper wallet
        isWeb2Login: false, // if true it will work as web2 login (Auth0)
        skipSignature: false, // if true it will skip the signature process
        theme: ConnectWalletTheme, // Custom connect wallet theme
      },
      walletOptions: {
        enableEmail: true,
        enableMetamask: true,
        enableWalletConnect: true,
      },
    }
    show={ show }
    token={ token } />
```
<br />

### Parameters:

| Prams                | Type     | Required | Description                                                                            |
| :------------------- | :------- | :------- | :------------------------------------------------------------------------------------- |
| uri                  | string   | ✅        | API url                                                                                |
| userInfo             | object   | ✅        | UserInfo                                                                               |
| show                 | boolean  | ✅        | to open checkout modal                                                                 |
| checkoutOptions      | object   | ✅       | CheckoutOptions                                                                        |
| theme                | object   |          | Theme                                                                                  |
| events               | object   |          | Events, you will get the logs                                                          |
| onClickConnectWallet | function |          | Your own connect wallet logic                                                          |
| walletDetails        | object   |          | pass connected wallet details if you add own connect wallet logic else no need to pass |
| uiConfiguration      | object   |          | UIConfiguration                                                                        |
| success              | boolean  |          | to show success popup                                                                  |
| token                | string   |          | pass bearer token                                                                      |
| debug                | boolean  |          | if true you will see the logs                                                          |

### UserInfo

| Prams | Type   | Description         |
| :---- | :----- | :------------------ |
| email | string | To show email in UI |

### CheckoutOptions

| Prams            | Type    | Description                                |
| :--------------- | :------ | :----------------------------------------- |
| orgId            | string  | Your organization id                       |
| lotId            | string  | Lot id you will get from mint portal       |
| quantity         | number  | quantity of the token                      |
| paymentId        | string  | paymentId for the success popup            |
| collectionItemId | string  | Pass item Id to get the details of an item |
| discountCode     | string  | coupon code                                |
| vertexEnabled    | boolean | to calculate tax                           |
| invoiceId        | string  | pass invoiceId for auction case            |
| successURL       | string  | success Redirect URL                       |
| errorURL         | string  | error Redirect URL                         |

### walletDetails

| Prams                 | Type     | Description                                                       |
| :-------------------- | :------- | :---------------------------------------------------------------- |
| wallet                | object   | Pass connected Wallet details if you add your own wallet logic    |
| saveWalletData        | function | In the function callback you can get the connected wallet details |
| onDisconnect          | number   | To handle your own disconnect function                            |
| onClickRefetchBalance | string   | To handle your own re-fetch function                              |

### UI Configuration

| Prams                | Type   | Description                    |
| :------------------- | :----- | :----------------------------- |
| global               | object | Global config                  |
| payment              | object | Payment Config                 |
| costBreakdown        | object | Const breakdown UI config      |
| paymentConfirmation  | object | Payment confirmation UI config |
| delivery             | object | Delivery UI config             |
| walletConnect        | object | Connect Wallet SDK config      |
| walletOptions        | object | Connect wallet options         |
| breadCrumbs          | array  | Custom breadCrumbs name        |
| isAutoFillCountryCode| boolean| To enable auto fill countryCode|

### Global Config

| Prams          | Type   | Description |
| :------------- | :----- | :---------- |
| logoSrc        | string | Logo url    |
| loaderImageSrc | string | loader url  |
| errorImageSrc  | string | error url   |

### Payment config

| Prams         | Type    | Description              |
| :------------ | :------ | :----------------------- |
| walletConnect | boolean | To enable wallet connect |
| wire          | boolean | To enable wire           |
| creditCard    | boolean | To enable credit card    |
| coinbase      | boolean | To enable coinbase       |

### Cost breakdown config

| Type                     | Description |                                          |
| :----------------------- | :---------- | :--------------------------------------- |
| showDiscountCode         | boolean     | To hide or show discount UI              |
| showProductionDisclaimer | boolean     | To hide or show production disclaimer UI |
| productDisclaimerText    | string      | Custom product disclaimer text           |

### Payment Confirmation

| Type                     | Description |                                                 |
| :----------------------- | :---------- | :---------------------------------------------- |
| wireTransferInstructions | JSX Element | Custom component for wire transfer instructions |
| creditCardInstructions   | JSX Element | Custom component for credit card instructions   |
| metamaskInstructions     | JSX Element | Custom metamask instructions                    |
| onGoTo                   | function    | Function to handle back to marketplace button   |

### Delivery Config

| Prams         | Type    | Description                  |
| :------------ | :------ | :--------------------------- |
| walletConnect | Object | MojitoDeliveryType            |
| wire          | Object | MojitoDeliveryType            |
| creditCard    | Object | MojitoCheckoutDeliveryType    |
| coinbase      | Object | MojitoDeliveryType            |
| description   | JSX Element (or) string | Description for Delivery      |

#### MojitoDeliveryType

| Prams           | Type    | Description              |
| :-------------- | :------ | :----------------------- |
| enableMultiSig  | boolean |

#### MojitoCheckoutDeliveryType

| Prams         | Type    | Description              |
| :------------ | :------ | :----------------------- |
| enableMultiSig| boolean |
| apiKey        | string  | api key for credit card payment  |

### Wallet connect config

| Prams                  | Type    | Description                                    |
| :--------------------- | :------ | :--------------------------------------------- |
| walletConnectProjectId | boolean | Wallet connect project id                      |
| paperClientId          | boolean | Email wallet paper client id                   |
| content                | object | To customise the connect wallet modal contents |
| isWeb2Login            | boolean | Connect wallet by web2 login                   |
| skipSignature          | boolean | Connect wallet by skipping signature process   |
| theme                  | Theme   | Customise the wallet connect theme             |
| clientId               | string  |
| activeChain            | string  |
| isPaperWallet          | boolean |

### Wallet Options

| Type                | Description |                                       |
| :------------------ | :---------- | :------------------------------------ |
| enableEmail         | boolean     | To hide or show Email wallet button   |
| enableMetamask      | boolean     | To hide or show metamask button       |
| enableWalletConnect | boolean     | To hide or show wallet connect button |

## Connect wallet theme:

```
  import { createTheme } from '@mui/material/styles';

  export const ConnectWalletTheme = createTheme({
    typography: {
      fontFamily: 'untitled_sansregular_regular',
    },
    components: {
      MuiTextField: {
        styleOverrides: {
          root: {
            '& input::-webkit-outer-spin-button, & input::-webkit-inner-spin-button':
                {
                  display: 'none',
                },
            '& input[type=number]': {
              MozAppearance: 'textfield',
            },
          },
        },
      },
      MuiCssBaseline: {
        styleOverrides: `
                  @font-face {
                    font-family: untitled_sansregular_regular;
                    font-style: normal;
                    font-display: swap;
                    font-weight: 400;
                    text-transform: none;
                    font-size: 16px;
                    color: #000;
                  }
                `,
      },
      MuiButton: {
        styleOverrides: {
          root: {
            fontFamily: 'untitled_sansregular_regular',
            textTransform: 'none',
            borderRadius: '4px',
            fontWeight: 700,
            fontSize: '16px',
            border: '1px solid #242629',
            backgroundColor: '#fff',
            color: '#242629',
            '&:hover': {
              backgroundColor: '#fff',
              color: '#242629',
              opacity: 0.5,
            },
          },
        },
      },
      MuiDialog: {
        styleOverrides: {
          paper: {
            border: '1px solid #D7D8DB',
            boxShadow: '0px 8px 16px rgba(0, 0, 0, 0.08)',
            borderRadius: '4px',
          },
        },
      },
      MuiDivider: {
        variants: [
          {
            props: { orientation: 'horizontal' },
            style: {
              ':before': {
                borderTop: 'thin solid #D7D8DB',
              },
              ':after': {
                borderTop: 'thin solid #D7D8DB',
              },
            },
          },
        ],
      },
    },
    palette: {
      primary: {
        main: '#242629',
      },
      secondary: {
        main: '#A6FF00',
      },
      backgroundColor: {
        primary: '#ffffff',
        secondary: '#000000',
      },
      grey: {
        100: '#F5F5F5',
        500: '#9E9E9E',
      },
      toastError: {
        500: '#CE2818',
      },
    },
  });

```

<br />

### Checkout Options

 Address Validation & Tax Calculation with Vertex or TaxJar

If you'd like address to be validated and taxes to be calculated during the checkout process, particularly in the Billing
Information step, you need a Vertex or TaxJar account. Once you have it, you need to configure it in Mojito Mint.

Alternatively, set the following prop to disable those calls to the backend: `vertexEnabled = false`.
  
<br />
 
```
  <MojitoCheckout
      checkoutOptions={{
        orgId: 'd086ea16-d40d-454c-84a4-64b5e940670a',
        lotId: '17cd1000-323d-4a20-8e5f-7a8598ffae2a',
        quantity: 1,
        paymentId: '<payment id>',
        collectionItemId: '64e99437-ac2e-45bc-b4a6-4750985b4e81',
        discountCode: 'ZZTO',
        vertexEnabled: false,
      }} />
  ```

### Supported Countries

We use Checkout for payments, so the supported countries depend on which payment method is going to be used, as described here:

- https://www.checkout.com/docs

<br />
  


### (Secret) Debug Mode

If you quickly click the logo in the top-right corner 16 times, the debug mode will be enabled (toggled, actually), even in production and regardless of
the initial value you passed for the `debug` prop.

The debug mode will, among logging/displaying some other less relevant pieces of data:

<br />


- Show form values and errors as JSON below the form:

  ![Debug form console](./screenshots/debug-console.png)
  <br />
  ![Debug form values and errors](./screenshots/debug-ui.png)

<br />

<br />

### Error page
Create an error page with the page path `/payments/failure`:

### Success page
Create an success page with the page path `/payments/success`:

The `success` parameter should be passed as true to the `MojitoCheckout` component.

```
  <MojitoCheckout
      userInfo={{
        email: email, // pass the user email
      }}
      checkoutOptions={{
        paymentId,
      }}
      show={ true }
      success={ true }
      uiConfiguration={{
        paymentConfirmation: {
          onGoTo: onClickGoToMarketPlace,
        },
      }} />
  ```

<br />

<br />

### Theme
You can use the themeOptions or theme props to pass a custom theme or theme options object:

themeOptions (preferred) will merge Mojito's default theme with your custom one

If none is provided, the default Mojito theme will be used.

```
  const DefaultThemes: ThemeConfiguration = {
      font: {
        primary: 'Sneak',
        secondary: 'Sneak',
      },
      color: {
        primary: '#6663FD',
        secondary: '#FFFFFF',
        background: '#FAFAFC',
        errorBackground: '#FEE3E5',
        text: '#000000',
        cardBackground: '#FFFFFF',
        checkout: {
          continueButtonBackground: '#6663FD',
          continueButtonTextColor: '#FFFFFF',
        },
        placeholder: '#BABEC5',
        costBreakdown: {
          applyButtonBackground: '#DADAE9',
          applyButtonTextColor: '#FFFFFF',
        },
      },
    };
  ```


Note that using MUI's ThemeProvider from your project won't work as expected and you will end up seeing Mojito's default theme:

```
<MojitoCheckout theme={ theme }
```

## React specific config:

If you are facing any issues regarding the Webpack polyfill in React.js applications while integrating this SDK, please follow these steps:

Step 1: Run either npm install or yarn install.
<br />
Step 2:
<br />
  a) Before running the app, execute the following script once.<br />
  b) Create a file named (filename).js in the root of the project folder and paste the code from this GitHub repository:
  [Development setup](https://github.com/mojitoinc/mojito-sdk/blob/main/script/polyfill.js)
<br />
Step 3: In the package.json, add a new script called "prebuild": "node {name of the js file that you added}" and run the command npm run prebuild.
<br />
Step 4: Now, you can run the application.

## Mixer development
[Development setup](./Development.md)