PaymentMethods component

Loop Connect's "Payment Methods" component renders a customizable UI for users to manage their saved payment methods, including viewing, editing authorization amounts, adding new methods, and setting default payment methods.

This document outlines the interface for adding a component to a React-based project. For those who wish to utilize a Javascript native web component for rendering into any project that supports them, like Vue or Svelte, use this page as a guide for usage and types, and use our Web component guide for assistance with native web component syntax.

Customer identification

The following properties ("props") are added to the LoopConnectPaymentMethods component to identify which customer's payment methods to manage. At least one of these properties should be provided.

<LoopConnectPaymentMethods 
    customerId="cust_abc123"
    // OR
    customerRefId="usr_abc1234"
/>
Property nameType or exampleDescription
customerIdstring, eg. "cust_abc123"The unique identifier for an existing customer record. Will be prioritized over customerRefId if both exist.
customerRefIdstring, eg. "usr_abc1234"The unique identifier specified by you for an existing or new customer record. If a new customer is created, this value will be stored as the customerRefId.
minimumAuthorizationUsdAmountnumber, eg. 199 (for $1.99)The minimum USD equivalent the user must authorize from their wallet in the selected token. If no value is set, authorization amounts can be set to any value.
disabledboolean (default is false)Disables UI components such that they can not be interacted with by the client.

Payment Methods events

The LoopConnectPaymentMethods component also accepts optional event callback handlers. The callback functions take the form (detail: EventType) => void, where EventType is a placeholder to represent the individually defined type for each event, specified below.

EventCallback typesDescription
onPaymentMethodsReadyPaymentMethodsReadyEventThe component has received the necessary data and is ready for user interaction.
onPaymentMethodsReadyFailedPaymentMethodsReadyFailedEventThe component failed to initialize.
onPaymentMethodsStateChangePaymentMethodsStateChangeEventOnce a user initiates an action, this component calls back with each step to allow you to provide detailed notifications for your users. Details on the payment method states is provided below.
onPaymentMethodsTokenChangePaymentMethodsTokenChangeEventThe user has changed the selected token they wish to use when adding a new payment method
onPaymentMethodsAuthorizationUpdatedPaymentMethodsAuthorizationUpdatedEventThe user has updated their wallet's authorization to transfer the selected token to the contract
onPaymentMethodsCustomerCreatedPaymentMethodsCustomerCreatedEventA record was created for this customer
onPaymentMethodsCreatedPaymentMethodsCreatedEventA new payment method was created and saved to the customer account
onPaymentMethodsUpdatedPaymentMethodsUpdatedEventAn existing payment method was updated (e.g., set as default)
onPaymentMethodsDeletedPaymentMethodsDeletedEventA payment method was deleted from the customer account
onPaymentMethodsFailedPaymentMethodsFailedEventAn action failed to complete. Details on the failure types is provided below.

💡

Both onWalletChange and onNetworkChange (defined above as initLoopConnect properties) can be provided in the same format to the LoopConnectPaymentMethods component for your convenience. Just note that each individual component will trigger their own provided callback for the same event occurrence, as these events are tied to the user's wallet which is a single connection shared application wide.

Callback prop types

The PaymentMethods event callback functions receive data about the event through a single property, where each event receives an object with a different type. The following types correspond to the types specified in the "Payment Methods events" table above.

interface PaymentMethodsReadyEvent {
    merchantId: string;
}
interface PaymentMethodsReadyFailedEvent {
    type: "paymentMethodsReadyFailed";
    message: string;
    data: Record<string, any>;
}
interface PaymentMethodsTokenChangeEvent {
    address: string;
    networkId: number;
    name: string;
    symbol: string;
    decimals: number;
    logoUrl: string;
    exchange: ExchangeRateDetails;
}
interface PaymentMethodsStateChangeEvent {
    state: 
        | "findingCustomer"
        | "idle" 
        | "editingAuthorization"
        | "selectingMethod"
        | "updatingMethod"
        | "deletingMethod"
        | "addingMethod"
        | "confirmingBalance"
        | "confirmingAuthorization" 
        | "updatingAuthorization" 
        | "signingMessage" 
        | "creatingCustomer" 
        | "creatingPaymentMethod";
    message: string;
    data: /* see "onPaymentMethodsStateChange states" for types */;
}
interface PaymentMethodsAuthorizationUpdatedEvent {
    authorizationAmount: string;
    suggestedAuthorizationTokenAmount: string | undefined;
    minimumAuthorizationTokenAmount: string | undefined;
    tokenAddress: string;
    tokenSymbol: string;
    networkId: number;
    walletAddress: string;
    existingAuthorizationAmount: string | null;
}
interface PaymentMethodsCustomerCreatedEvent {
    customerId: string;
    customerRefIds: {
        merchantId: string;
        customerRefId: string;
    }[];
    paymentMethods: {
        paymentMethodId: string;
        paymentMethodName: string;
        networkId: number;
        walletAddress: string;
        isDefault: boolean;
        token: {
            tokenId: string;
            symbol: string;
            address: string;
            decimals: number;
            exchangeRates: {
                currency: string;
                price: string;
                timestamp: number;
            }[];
        };
        preAuthorization: {
            balance: string;
            authorization: string;
        };
    }[];
    dateCreated: number;
}
interface PaymentMethodsCreatedEvent {
    paymentMethodId: string;
    merchantId: string;
    paymentMethodName: string;
    networkId: number;
    walletAddress: string;
    isDefault: boolean;
    token: {
        tokenId: string;
        symbol: string;
        address: string;
        decimals: number;
        exchangeRates: {
            currency: string;
            price: string;
            timestamp: number;
        }[];
    };
    preAuthorization: {
        balance: string;
        authorization: string;
    };
}
interface PaymentMethodsUpdatedEvent {
    paymentMethodId: string;
    merchantId: string;
    paymentMethodName: string;
    networkId: number;
    walletAddress: string;
    isDefault: boolean;
    token: {
        tokenId: string;
        symbol: string;
        address: string;
        decimals: number;
        exchangeRates: {
            currency: string;
            price: string;
            timestamp: number;
        }[];
    };
    preAuthorization: {
        balance: string;
        authorization: string;
    };
}
interface PaymentMethodsDeletedEvent {
    paymentMethodId: string;
    merchantId: string;
    paymentMethodName: string;
    networkId: number;
    walletAddress: string;
    isDefault: boolean;
    token: {
        tokenId: string;
        symbol: string;
        address: string;
        decimals: number;
        exchangeRates: {
            currency: string;
            price: string;
            timestamp: number;
        }[];
    };
    preAuthorization: {
        balance: string;
        authorization: string;
    };
}
interface PaymentMethodsFailedEvent {
	type:
        | "methodCreationFailed"
        | "insufficientBalance"
        | "authorizationFailed"
        | "insufficientAuthorization"
  	    | "signedMessageRequired"
  	    | "customerCreationFailed"
        | "selectMethodFailed"
        | "deleteMethodFailed";
	message: string;
	data: {
		error: Record<string, any> | undefined;
	};
}

onPaymentMethodsStateChange

The onPaymentMethodsStateChange event handler will receive an object which contains the state property set to one of the following string values indicating the component's current state.

<LoopConnectPaymentMethods 
    // other props
    onPaymentMethodsStateChange={
        ({ state, message, data }) => console.log(`${state}: ${message}`, data);
    } 
/>
StateEvent data object typeDescription
findingCustomerPaymentMethodsStateChangeEventFindingCustomerLooking up existing payment methods for the provided customer ID or customer reference ID
idlePaymentMethodsStateChangeEventIdleThe default state showing the customer's default payment method
editingAuthorizationPaymentMethodsStateChangeEventEditingAuthorizationThe user is editing the authorization amount for the default payment method
selectingMethodPaymentMethodsStateChangeEventSelectingMethodShowing all available payment methods for the customer to select from
updatingMethodPaymentMethodsStateChangeEventUpdatingMethodA payment method is being updated (e.g., set as default)
deletingMethodPaymentMethodsStateChangeEventDeletingMethodA payment method is being deleted
addingMethodPaymentMethodsStateChangeEventAddingMethodThe user is adding a new payment method
confirmingBalancePaymentMethodsStateChangeEventConfirmingBalanceAwaiting a response back from the blockchain to confirm the wallet's balance is sufficient in the selected token on the wallet's current network
confirmingAuthorizationPaymentMethodsStateChangeEventConfirmingAuthorizationAwaiting a response back from the blockchain to confirm the wallet's authorization is sufficient in the selected token on the wallet's current network for the contract required
updatingAuthorizationPaymentMethodsStateChangeEventUpdatingAuthorizationThe wallet's authorization was insufficient and is now awaiting confirmation that the user has completed their wallet's prompt to update the amount
signingMessagePaymentMethodsStateChangeEventSigningMessageAwaiting a signed message from the user's wallet which has prompted them to authorize Loop Crypto to process payments
creatingCustomerPaymentMethodsStateChangeEventCreatingCustomerAwaiting confirmation that a customer record was created
creatingPaymentMethodPaymentMethodsStateChangeEventCreatingPaymentMethodAwaiting confirmation that a payment method was created and saved

State data object types

In addition to supplying the state and a human-readable message describing the event, a unique data object containing information about the state is provided. The following types correspond to the types specified in the "onPaymentMethodsStateChange states" table above.

interface PaymentMethodsStateChangeEventFindingCustomer {
    customerId?: string;
    customerRefId?: string;
    merchantId: string;
}
interface PaymentMethodsStateChangeEventIdle {
    /* no additional data is provided for the idle state */
}
interface PaymentMethodsStateChangeEventEditingAuthorization {
    tokenAddress: string;
    tokenSymbol: string;
    currentAuthorizationAmount: string | undefined;
    minimumAuthorization: string | undefined;
}
interface PaymentMethodsStateChangeEventSelectingMethod {
    /* no additional data is provided for the selecting method state */
}
interface PaymentMethodsStateChangeEventUpdatingMethod {
    paymentMethodId?: string;
}
interface PaymentMethodsStateChangeEventDeletingMethod {
    paymentMethodId?: string;
}
interface PaymentMethodsStateChangeEventAddingMethod {
    /* no additional data is provided for the adding method state */
}
interface PaymentMethodsStateChangeEventConfirmingBalance {
    amount: string;
    walletAddress: string;
    chain: BlockchainNetwork;
    networkName: string;
    token: {
        name: string;
        logoUrl: string;
        symbol: string;
        decimals: number;
        address: string;
        networkId: number;
        exchange: {
            currency: string;
            rate: number;
            updated: number;
            provider: string;
        };
    }
}
interface PaymentMethodsStateChangeEventConfirmingAuthorization {
    minimumAuthorization: string | undefined;
    contractAddress: string;
    walletAddress: string;
    chain: BlockchainNetwork;
    networkName: string;
    token: {
        name: string;
        logoUrl: string;
        symbol: string;
        decimals: number;
        address: string;
        networkId: number;
        exchange: {
            currency: string;
            rate: number;
            updated: number;
            provider: string;
        };
    }
}
interface PaymentMethodsStateChangeEventUpdatingAuthorization {
    suggestedAuthorization: string | undefined;
    contractAddress: string;
    walletAddress: string;
    chain: BlockchainNetwork;
    networkName: string;
    existingAuthorization: string | null;
    token: {
        name: string;
        logoUrl: string;
        symbol: string;
        decimals: number;
        address: string;
        networkId: number;
        exchange: {
            currency: string;
            rate: number;
            updated: number;
            provider: string;
        };
    }
}
interface PaymentMethodsStateChangeEventSigningMessage {
    walletAddress: string;
    chain: BlockchainNetwork;
    networkName: string;
    networkId: number;
}
interface PaymentMethodsStateChangeEventCreatingCustomer {
    walletAddress: string;
    chain: BlockchainNetwork;
    networkName: string;
    token: {
        name: string;
        logoUrl: string;
        symbol: string;
        decimals: number;
        address: string;
        networkId: number;
        exchange: {
            currency: string;
            rate: number;
            updated: number;
            provider: string;
        };
    }
}
interface PaymentMethodsStateChangeEventCreatingPaymentMethod {
    walletAddress: string;
    chain: BlockchainNetwork;
    networkName: string;
    customerId: string;
    customerRefId?: string;
    token: {
        name: string;
        logoUrl: string;
        symbol: string;
        decimals: number;
        address: string;
        networkId: number;
        exchange: {
            currency: string;
            rate: number;
            updated: number;
            provider: string;
        };
    }
}

onPaymentMethodsFailed

The onPaymentMethodsFailed event handler will receive an object which contains the type property set to one of the following string values indicating the reason the action was not completed successfully.

<LoopConnectPaymentMethods 
    // other props
    onPaymentMethodsFailed={
        ({ type, message, data }) => console.log(`${type}: ${message}`, data);
    } 
/>
Failure typeDescription
methodCreationFailedThere was a problem creating the new payment method
insufficientBalanceThe wallet connected does not have the sufficient amount of token on the current network
authorizationFailedThe wallet failed to update the authorization amount for the selected token
insufficientAuthorizationThe user has not granted sufficient authorization for this token to meet the minimum requirements on the wallet's current network
signedMessageRequiredThe wallet failed to sign a message to approve the creation or management of payment methods
customerCreationFailedThere was a problem creating or updating the customer record
selectMethodFailedThere was a problem updating the default payment method selection
deleteMethodFailedThere was a problem deleting the payment method

Failure data object types

For onPaymentMethodsFailed events, the data object contains an error object of the type Record<string, any>, which returns details about the error, and in most cases is a native Javascript Event object.

User interface

You can provide optional properties to allow for customization of the UI to more seamlessly match your application's look and feel.

Styling

The component's UI can be customized by providing a string of CSS custom properties and values. The values assigned to the property must be valid CSS for that type of property, which corresponds to a CSS declaration. In the table below, each custom property is linked to the corresponding CSS property it represents to ensure clarity.

<LoopConnectPaymentMethods 
    // other props
    customStyles={`
        --loop-connect-font: italic 700 1rem 'Poppins', sans-serif;
        --loop-connect-widget-shadow: 0 0 0.5rem rgba(99,99,99,0.3);
    `} 
/>
PropertyCSS property or typeDescription
--loop-connect-color-primary<color>Used as an accent color, primarily for button background, but not exclusively backgrounds
--loop-connect-color-on-primarycolorUsed as the text or accent color when shown within subcomponents colored with the primary color
--loop-connect-radiusborder-radiusDefines the roundness of box corners. Also applies to the entire widget, unless ``--loop-connect-widget-radius` overrides it
--loop-connect-color-textcolorDefines the color of text
--loop-connect-fontfontAssigns the size, weight, style and family for the font used as the main copy within the component
--loop-connect-widget-borderborderDefines the border around the entire widget
--loop-connect-widget-radiusborder-radiusDefines the roundness of the corners of the widget. Will override --loop-connect-radius if set
--loop-connect-widget-paddingpaddingSpecifies the padding around the outside of the component
--loop-connect-widget-shadowbox-shadowSpecifies the styling of the outer shadow around the component
--loop-connect-widget-backgroundbackgroundSets the background color of the component
--loop-connect-input-borderborderOverrides the default border style of input and select subcomponents
--loop-connect-input-backgroundbackgroundAssigns a background color to input and select subcomponents

💡

Note that the customStyles property can also be provided to the initLoopConnect as a property and will apply the styles to all Loop Connect components application-wide. Properties then applied to individual components will override those app-wide values, creating a cascade effect.


Quickstart example

import { StrictMode } from "react";
import { createRoot } from "react-dom/client";

// 1. Import the package
import { initLoopConnect, LoopConnectPaymentMethods } from "@loop-crypto/connect";

// 2. Initialize is outside of the application
initLoopConnect({
    jwtToken: "your-jwt-token-here",
    entityId: "your-entity-id-here",
    merchantId: "your-merchant-id-here",
});

// 3. Add the PaymentMethods component to the React application
createRoot(document.getElementById("root")!).render(
    <StrictMode>
        <LoopConnectPaymentMethods
            customerRefId="test-user-id"
        />
    </StrictMode>
);