@terra-js/crypto-payment
TypeScript icon, indicating that this package has built-in type declarations

1.0.3-prod • Public • Published

@terra-js/crypto-payment

Install the library

yarn add @terra-js/crypto-payment

How to use

Initialize

  • Call once to init the library globally
import {
  setLanguage,
  setClientId
} from '@terra-js/crypto-payment';

// call once to init
setLanguage('en');
setClientId('dinogo:web:playstore:0.0.1');

Input

// payment amount must be a valid positive number or a string presenting a valid positive number
// we encourage to use string if you need more accuracy
const PAYMENT_AMOUNT = '15.5'

// orderCode is a string defining the order in your system
const ORDER_CODE = '123456ABCD'

Style A: use PaymentCryptoComponent

import {
  PaymentCryptoComponent,
  ExposeErrorCode
} from '@terra-js/crypto-payment';

function App() {
  return (
    <div className="App">
      <PaymentCryptoComponent paymentAmount={PAYMENT_AMOUNT} orderCode={ORDER_CODE} onPaymentResult={(result) => {
        switch (result.code) {
          case ExposeErrorCode.Success:
            setResult("Success")
            break
          case ExposeErrorCode.VerifyTransactionHashFailed:
            setResult(`VerifyTransactionHashFailed: ${result.message}`)
            break
          case ExposeErrorCode.WaitNotificationFailed:
            setResult(`WaitNotificationFailed: ${result.message}`)
            break
          case ExposeErrorCode.UserCloseWaitNotificationPopup:
            setResult(`UserCloseWaitNotificationPopup: ${result.message}`);
            break;
        }
      }}/>
    </div>
  );
}

export default withPaymentCryptoProvider(App);

Style B: use PaymentCryptoButton & PaymentCryptoModal separately

import {
  PaymentCryptoButton,
  PaymentCryptoModal,
  ExposeErrorCode
} from '@terra-js/crypto-payment';

function App() {
  const [showPaymentCryptoPopup, setShowPaymentCryptoPopup] = useState(false);

  return (
    <div className="App">
      <PaymentCryptoButton
        onClickForPayment={() => {
          setShowPaymentCryptoPopup(true);
        }}
      />
      <PaymentCryptoModal
        isOpen={showPaymentCryptoPopup}
        paymentAmount={PAYMENT_AMOUNT}
        orderCode={ORDER_CODE}
        onCloseModal={() => {
          setShowPaymentCryptoPopup(false);
        }}
        onPaymentResult={(result) => {
          console.log('crypto-payment-modal-result', result);
          switch (result.code) {
            case ExposeErrorCode.Success:
              setResult('Success');
              break;
            case ExposeErrorCode.VerifyTransactionHashFailed:
              setResult(`VerifyTransactionHashFailed: ${result.message}`);
              break;
            case ExposeErrorCode.WaitNotificationFailed:
              setResult(`WaitNotificationFailed: ${result.message}`);
              break;
            case ExposeErrorCode.UserCloseWaitNotificationPopup:
              setResult(`UserCloseWaitNotificationPopup: ${result.message}`);
              break;
          }
        }}
      />
    </div>
  );
}

export default withPaymentCryptoProvider(App);

Style C: use own button to trigger PaymentCryptoModal and Disconnect

import {
    ExposeErrorCode,
    PaymentCryptoModal,
    setClientId,
    setLanguage,
    withPaymentCryptoProvider,
    useDisconnectWallet,
    PaymentCryptoContext,
    Result
} from '@terra-js/crypto-payment';

function App() {
    const { walletState } = useContext(PaymentCryptoContext);
    const [result, setResult] = useState('');
    const [showPaymentCryptoPopup, setShowPaymentCryptoPopup] = useState(false);
    const {disconnect} = useDisconnectWallet()

    const onClickPayButton = async () => {
        setShowPaymentCryptoPopup(true);
    };

    const handlePaymentResult = (result: Result<void>) => {
        switch (result.code) {
            case ExposeErrorCode.Success:
                setResult('Success');
                break;
            case ExposeErrorCode.VerifyTransactionHashFailed:
                setResult(`VerifyTransactionHashFailed: ${result.message}`);
                break;
            case ExposeErrorCode.WaitNotificationFailed:
                setResult(`WaitNotificationFailed: ${result.message}`);
                break;
            case ExposeErrorCode.UserCloseWaitNotificationPopup:
                setResult(`UserCloseWaitNotificationPopup: ${result.message}`);
                break;
        }
    };

    const onDisconnect = () => {
        disconnect();
    }

    return (
        <div className='App'>
            <header className='App-header'>
                <div style={{ display: 'flex', flexDirection: 'column', color: 'black', fontSize: 14 }}>
                    {walletState.isConnected && (
                        <div style={{ display: 'flex', flexDirection: 'row', alignItems: 'center' }}>
                            <img
                                src={walletState.walletIcon}
                                alt='wallet-icon'
                                style={{ margin: `12px 0 0 0` }}
                                width={36}
                                height={36}
                            />
                            <p style={{ margin: `12px 0 0 0` }}>{walletState.stakeKey ? walletState.stakeKey : walletState.walletAccountAddress}</p>
                        </div>
                    )}
                </div>
                <PaymentCryptoModal
                    isOpen={showPaymentCryptoPopup}
                    paymentAmount={PAYMENT_AMOUNT}
                    orderCode={ORDER_CODE}
                    onCloseModal={() => {
                        setShowPaymentCryptoPopup(false);
                    }}
                    onPaymentResult={(result) => {
                        console.log('crypto-payment-modal-result', result);
                        handlePaymentResult(result);
                    }}
                />
                <div style={{ height: 1, width: 200, backgroundColor: 'gray', margin: 16 }} />
                <div className='crypto-pay-button' style={{ height: 55 }} onClick={onClickPayButton}>
                    <div className='crypto-pay-button-inner' style={{ color: '#1990FF' }}>
                        Payment
                    </div>
                </div>
                
                <div style={{ height: 1, width: 200, backgroundColor: 'gray', margin: 16 }} />
                <div className='crypto-pay-button' style={{ height: 55 }} onClick={onDisconnect}>
                    <div className='crypto-pay-button-inner' style={{ color: '#1990FF' }}>
                        Disconnect
                    </div>
                </div>
                
                <div style={{ height: 1, width: 200, backgroundColor: 'gray', margin: 16 }} />
                <div style={{ color: 'black' }}>Result: {result}</div>
            </header>
        </div>
    );
}

export default withPaymentCryptoProvider(App);

Handling results

result.code meaning
ExposeErrorCode.Success Everything is success
ExposeErrorCode.VerifyTransactionHashFailed Transaction sent to network, but no IPNs were fired to your backend. Client should notice user to contact admin to manually confirm the transaction.
ExposeErrorCode.WaitNotificationFailed Transaction sent to network, IPN will be fired to your backend. Client should instruct user to refresh the order for new state
ExposeErrorCode.UserCloseWaitNotificationPopup Transaction sent to network, but user waited for so long and close the popup. Client should instruct user to refresh the order for new state

Utils

getCurrentMetamaskAccount
  • Return undefined if no accounts detected
  • return public address of current selected account in Metamask
import { getCurrentMetamaskAccount } from '@terra-js/crypto-payment';

const address = await getCurrentMetamaskAccount();
listen for account changed
useEffect(() => {
  const listener = registerAccountsChanged((account: string) => {
    console.log('accountChanged', account);
  });

  return () => {
    listener && unregisterAccountsChanged(listener);
  };
}, []);

Import the library's css

Import it at appropriated place:

import '@terra-js/crypto-payment/dist/styles/PaymentCrypto.css';

Specifically for Next-js

  • Install following devDependencies
yarn add -D next-compose-plugins // install a version that should be compatible with your next-js version
yarn add -D next-transpile-modules // install a version that should be compatible with your next-js version
  • Add config in next.config.js
/** @type {import('next').NextConfig} */
const withPlugins = require('next-compose-plugins');
const withTM = require('next-transpile-modules')([
  '@terra-js/crypto-payment',
]);

const nextConfig = {
  // your config here
}

module.exports = withPlugins([withTM], nextConfig)

Some issues when running app

1. Warning when generating source map For example:

Failed to parse source map from '/path/on/device/AtomicFU.common.kt' file: Error: ENOENT: no such file or directory, open '/path/on/device/AtomicFU.common.kt'
``

This issue may be caused when starting app with react-scripts command like react-scripts start (projects are created by react-react-app).

To fix this, please add GENERATE_SOURCEMAP=false option to the start/build command. For example:

"start": "GENERATE_SOURCEMAP=false react-scripts start",
"build": "GENERATE_SOURCEMAP=false react-scripts build",

Package Sidebar

Install

npm i @terra-js/crypto-payment

Weekly Downloads

6

Version

1.0.3-prod

License

MIT

Unpacked Size

3.45 MB

Total Files

98

Last publish

Collaborators

  • mobile.admin.teko