UNPKG

@reown/appkit-scaffold-ui

Version:

The full stack toolkit to build onchain app UX.

288 lines (286 loc) • 10.9 kB
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; import { LitElement, html } from 'lit'; import { state } from 'lit/decorators.js'; import { NumberUtil } from '@reown/appkit-common'; import { AssetUtil, ChainController, ConnectionController, ConstantsUtil, CoreHelperUtil, ModalController, RouterController, SendController, SnackController, SwapController } from '@reown/appkit-controllers'; import { BalanceUtil } from '@reown/appkit-controllers/utils'; import { customElement } from '@reown/appkit-ui'; import '@reown/appkit-ui/wui-button'; import '@reown/appkit-ui/wui-flex'; import '@reown/appkit-ui/wui-icon-box'; import '@reown/appkit-ui/wui-separator'; import '../../partials/w3m-input-address/index.js'; import '../../partials/w3m-input-token/index.js'; import styles from './styles.js'; const SEND_BUTTON_MESSAGE = { INSUFFICIENT_FUNDS: 'Insufficient Funds', INCORRECT_VALUE: 'Incorrect Value', INVALID_ADDRESS: 'Invalid Address', ADD_ADDRESS: 'Add Address', ADD_AMOUNT: 'Add Amount', SELECT_TOKEN: 'Select Token', PREVIEW_SEND: 'Preview Send' }; let W3mWalletSendView = class W3mWalletSendView extends LitElement { constructor() { super(); this.unsubscribe = []; this.isTryingToChooseDifferentWallet = false; this.token = SendController.state.token; this.sendTokenAmount = SendController.state.sendTokenAmount; this.receiverAddress = SendController.state.receiverAddress; this.receiverProfileName = SendController.state.receiverProfileName; this.loading = SendController.state.loading; this.params = RouterController.state.data?.send; this.caipAddress = ChainController.getAccountData()?.caipAddress; this.disconnecting = false; this.gasFee = SwapController.state.gasFee; if (this.token && !this.params) { this.fetchBalances(); this.fetchNetworkPrice(); } const unsubscribe = ChainController.subscribeKey('activeCaipAddress', val => { if (!val && this.isTryingToChooseDifferentWallet) { this.isTryingToChooseDifferentWallet = false; ModalController.open({ view: 'Connect', data: { redirectView: 'WalletSend' } }).catch(() => null); unsubscribe(); } }); this.unsubscribe.push(...[ ChainController.subscribeAccountStateProp('caipAddress', val => { this.caipAddress = val; }), SendController.subscribe(val => { this.token = val.token; this.sendTokenAmount = val.sendTokenAmount; this.receiverAddress = val.receiverAddress; this.receiverProfileName = val.receiverProfileName; this.loading = val.loading; }), SwapController.subscribeKey('gasFee', val => { this.gasFee = val; }) ]); } disconnectedCallback() { this.unsubscribe.forEach(unsubscribe => unsubscribe()); } async firstUpdated() { await this.handleSendParameters(); } render() { const message = this.getMessage(); const isReadOnly = Boolean(this.params); return html ` <wui-flex flexDirection="column" .padding=${['0', '4', '4', '4']}> <wui-flex class="inputContainer" gap="2" flexDirection="column"> <w3m-input-token .token=${this.token} .sendTokenAmount=${this.sendTokenAmount} .gasPrice=${this.gasFee} ?readOnly=${isReadOnly} ?isInsufficientBalance=${message === SEND_BUTTON_MESSAGE.INSUFFICIENT_FUNDS} ></w3m-input-token> <wui-icon-box size="md" variant="secondary" icon="arrowBottom"></wui-icon-box> <w3m-input-address ?readOnly=${isReadOnly} .value=${this.receiverProfileName ? this.receiverProfileName : this.receiverAddress} ></w3m-input-address> </wui-flex> ${this.buttonTemplate(message)} </wui-flex>`; } async fetchBalances() { await SendController.fetchTokenBalance(); SendController.fetchNetworkBalance(); } async fetchNetworkPrice() { await SwapController.getNetworkTokenPrice(); await SwapController.getInitialGasPrice(); } onButtonClick() { RouterController.push('WalletSendPreview', { send: this.params }); } onFundWalletClick() { RouterController.push('FundWallet', { redirectView: 'WalletSend' }); } async onConnectDifferentWalletClick() { try { this.isTryingToChooseDifferentWallet = true; this.disconnecting = true; await ConnectionController.disconnect(); } finally { this.disconnecting = false; } } getMessage() { if (!this.token) { return SEND_BUTTON_MESSAGE.SELECT_TOKEN; } if (!this.sendTokenAmount) { return SEND_BUTTON_MESSAGE.ADD_AMOUNT; } if (this.token.price) { const value = Number(this.sendTokenAmount) * this.token.price; if (!value) { return SEND_BUTTON_MESSAGE.INCORRECT_VALUE; } } if (NumberUtil.bigNumber(this.sendTokenAmount).gt(this.token.quantity.numeric)) { return SEND_BUTTON_MESSAGE.INSUFFICIENT_FUNDS; } if (!this.receiverAddress) { return SEND_BUTTON_MESSAGE.ADD_ADDRESS; } if (!CoreHelperUtil.isAddress(this.receiverAddress, ChainController.state.activeChain)) { return SEND_BUTTON_MESSAGE.INVALID_ADDRESS; } return SEND_BUTTON_MESSAGE.PREVIEW_SEND; } buttonTemplate(message) { const isDisabled = !message.startsWith(SEND_BUTTON_MESSAGE.PREVIEW_SEND); const isInsufficientBalance = message === SEND_BUTTON_MESSAGE.INSUFFICIENT_FUNDS; const isReadOnly = Boolean(this.params); if (isInsufficientBalance && !isReadOnly) { return html ` <wui-flex .margin=${['4', '0', '0', '0']} flexDirection="column" gap="4"> <wui-button @click=${this.onFundWalletClick.bind(this)} size="lg" variant="accent-secondary" fullWidth > Fund Wallet </wui-button> <wui-separator data-testid="wui-separator" text="or"></wui-separator> <wui-button @click=${this.onConnectDifferentWalletClick.bind(this)} size="lg" variant="neutral-secondary" fullWidth ?loading=${this.disconnecting} > Connect a different wallet </wui-button> </wui-flex> `; } return html `<wui-flex .margin=${['4', '0', '0', '0']}> <wui-button @click=${this.onButtonClick.bind(this)} ?disabled=${isDisabled} size="lg" variant="accent-primary" ?loading=${this.loading} fullWidth > ${message} </wui-button> </wui-flex>`; } async handleSendParameters() { this.loading = true; if (!this.params) { this.loading = false; return; } const amount = Number(this.params.amount); if (isNaN(amount)) { SnackController.showError('Invalid amount'); this.loading = false; return; } const { namespace, chainId, assetAddress } = this.params; if (!ConstantsUtil.SEND_PARAMS_SUPPORTED_CHAINS.includes(namespace)) { SnackController.showError(`Chain "${namespace}" is not supported for send parameters`); this.loading = false; return; } const caipNetwork = ChainController.getCaipNetworkById(chainId, namespace); if (!caipNetwork) { SnackController.showError(`Network with id "${chainId}" not found`); this.loading = false; return; } try { const { balance, name, symbol, decimals } = await BalanceUtil.fetchERC20Balance({ caipAddress: this.caipAddress, assetAddress, caipNetwork }); if (!name || !symbol || !decimals || !balance) { SnackController.showError('Token not found'); return; } SendController.setToken({ name, symbol, chainId: caipNetwork.id.toString(), address: `${caipNetwork.chainNamespace}:${caipNetwork.id}:${assetAddress}`, value: 0, price: 0, quantity: { decimals: decimals.toString(), numeric: balance.toString() }, iconUrl: AssetUtil.getTokenImage(symbol) ?? '' }); SendController.setTokenAmount(String(amount)); SendController.setReceiverAddress(this.params.to); } catch (err) { console.error('Failed to load token information:', err); SnackController.showError('Failed to load token information'); } finally { this.loading = false; } } }; W3mWalletSendView.styles = styles; __decorate([ state() ], W3mWalletSendView.prototype, "token", void 0); __decorate([ state() ], W3mWalletSendView.prototype, "sendTokenAmount", void 0); __decorate([ state() ], W3mWalletSendView.prototype, "receiverAddress", void 0); __decorate([ state() ], W3mWalletSendView.prototype, "receiverProfileName", void 0); __decorate([ state() ], W3mWalletSendView.prototype, "loading", void 0); __decorate([ state() ], W3mWalletSendView.prototype, "params", void 0); __decorate([ state() ], W3mWalletSendView.prototype, "caipAddress", void 0); __decorate([ state() ], W3mWalletSendView.prototype, "disconnecting", void 0); __decorate([ state() ], W3mWalletSendView.prototype, "gasFee", void 0); W3mWalletSendView = __decorate([ customElement('w3m-wallet-send-view') ], W3mWalletSendView); export { W3mWalletSendView }; //# sourceMappingURL=index.js.map