TxButton.tsx 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. // Copyright 2017-2020 @polkadot/react-components authors & contributors
  2. // This software may be modified and distributed under the terms
  3. // of the Apache-2.0 license. See the LICENSE file for details.
  4. import { SubmittableExtrinsic } from '@polkadot/api/types';
  5. import { TxButtonProps as Props } from './types';
  6. import React, { useCallback, useContext } from 'react';
  7. import { SubmittableResult } from '@polkadot/api';
  8. import { useApi, useToggle } from '@polkadot/react-hooks';
  9. import { assert, isFunction } from '@polkadot/util';
  10. import Button from './Button';
  11. import { StatusContext } from './Status';
  12. import { useTranslation } from './translate';
  13. function TxButton ({ accountId, className = '', extrinsic: propsExtrinsic, icon, isBasic, isBusy, isDisabled, isIcon, isUnsigned, label, onClick, onFailed, onSendRef, onStart, onSuccess, onUpdate, params, tooltip, tx, withSpinner }: Props): React.ReactElement<Props> {
  14. const { t } = useTranslation();
  15. const { api } = useApi();
  16. const { queueExtrinsic } = useContext(StatusContext);
  17. const [isSending, , setIsSending] = useToggle(false);
  18. const needsAccount = !isUnsigned && !accountId;
  19. const _onFailed = useCallback(
  20. (result: SubmittableResult | Error | null): void => {
  21. setIsSending(false);
  22. onFailed && onFailed(result);
  23. },
  24. [onFailed, setIsSending]
  25. );
  26. const _onSuccess = useCallback(
  27. (result: SubmittableResult): void => {
  28. setIsSending(false);
  29. onSuccess && onSuccess(result);
  30. },
  31. [onSuccess, setIsSending]
  32. );
  33. const _onSend = useCallback(
  34. (): void => {
  35. let extrinsic: SubmittableExtrinsic<'promise'>;
  36. if (propsExtrinsic) {
  37. extrinsic = propsExtrinsic;
  38. } else {
  39. const [section, method] = (tx || '').split('.');
  40. assert(api.tx[section] && api.tx[section][method], `Unable to find api.tx.${section}.${method}`);
  41. extrinsic = api.tx[section][method](...(
  42. isFunction(params)
  43. ? params()
  44. : (params || [])
  45. ));
  46. }
  47. assert(extrinsic, 'Expected generated extrinsic passed to TxButton');
  48. if (withSpinner) {
  49. setIsSending(true);
  50. }
  51. queueExtrinsic({
  52. accountId: accountId && accountId.toString(),
  53. extrinsic,
  54. isUnsigned,
  55. txFailedCb: withSpinner ? _onFailed : onFailed,
  56. txStartCb: onStart,
  57. txSuccessCb: withSpinner ? _onSuccess : onSuccess,
  58. txUpdateCb: onUpdate
  59. });
  60. onClick && onClick();
  61. },
  62. [_onFailed, _onSuccess, accountId, api.tx, isUnsigned, onClick, onFailed, onStart, onSuccess, onUpdate, params, propsExtrinsic, queueExtrinsic, setIsSending, tx, withSpinner]
  63. );
  64. if (onSendRef) {
  65. onSendRef.current = _onSend;
  66. }
  67. return (
  68. <Button
  69. className={className}
  70. icon={icon || 'check'}
  71. isBasic={isBasic}
  72. isBusy={isBusy}
  73. isDisabled={isSending || isDisabled || needsAccount}
  74. isIcon={isIcon}
  75. label={label || (isIcon ? '' : t<string>('Submit'))}
  76. onClick={_onSend}
  77. tooltip={tooltip}
  78. />
  79. );
  80. }
  81. export default React.memo(TxButton);