const MultiSenderWidget = ({ context, NearAPI }) => { // Initialize the state if (!state) { State.init({ tokenContract: "", csvInput: "", isConnected: context.accountId ? true : false, // Check if user is connected errorMessage: "", showModal: false, transactions: [], }); } const parseCSVtoJSON = (csvInput) => { const rows = csvInput .split(";") .map((row) => row.trim()) .filter((row) => row.length > 0); const formattedList = []; let errorMessage = ""; rows.forEach((row, index) => { const [recipient, amount] = row.split(",").map((item) => item.trim()); if (!recipient || !amount || isNaN(amount)) { errorMessage = `Invalid input in row ${index + 1}: ${row}`; return; } formattedList.push({ recipient, amount }); }); if (errorMessage) { State.update({ errorMessage }); return false; } else { return formattedList; } }; const handleMultiSend = () => { const csvInput = state.csvInput; const tokenContract = state.tokenContract; console.log("Button Clicked, State:", state); if (!csvInput) { State.update({ errorMessage: "CSV Input is empty or undefined" }); return; } const transactions = parseCSVtoJSON(csvInput); if (!transactions) { console.log("Validation failed:", state.errorMessage); return; } console.log("Parsed Transactions:", transactions); State.update({ transactions, showModal: true }); }; const confirmSendTokens = () => { const tokenContract = state.tokenContract; const transactions = state.transactions; // Prepare batch transactions const batchTransactions = transactions.map((tx) => ({ contractName: tokenContract, methodName: "ft_transfer", args: { receiver_id: tx.recipient, amount: tx.amount, }, gas: "300000000000000", // gas limit deposit: "1", // deposit, in yoctoNEAR })); Near.call(batchTransactions) .then(() => { console.log("Tokens sent successfully"); State.update({ errorMessage: "Tokens sent successfully!", showModal: false, }); }) .catch((error) => { console.error("Error during multisend:", error); State.update({ errorMessage: `Error during multisend: ${error.message}`, showModal: false, }); }); }; const handleCSVInput = (e) => { const csvInput = e.target.value; console.log("Updating CSV Input:", csvInput); State.update({ csvInput }); }; const handleTokenContractInput = (e) => { const tokenContract = e.target.value; console.log("Updating Token Contract:", tokenContract); State.update({ tokenContract }); }; const closeModal = () => { console.log("Closing Modal"); State.update({ showModal: false }); }; return ( <div> <h1>NEAR Social Multisender</h1> <div> <label>Token Contract:</label> <input type="text" value={state.tokenContract} onChange={handleTokenContractInput} /> </div> <br /> <div> <label>CSV Input:</label> <textarea placeholder="wallet1.near, amount1; wallet2.near, amount2; ..." value={state.csvInput} onChange={handleCSVInput} /> </div> <br /> <div> <button onClick={handleMultiSend}>Send Tokens</button> </div> <br /> {state.errorMessage && ( <div style={{ color: "red" }}> <strong>Error:</strong> {state.errorMessage} </div> )} <div> <h3>CSV Template:</h3> <p>wallet1.near, amount1; wallet2.near, amount2; ...</p> </div> {state.showModal && ( <div style={fixedModalStyle}> <div style={fixedModalContentStyle}> <h2>Confirm Transactions</h2> <ul> {state.transactions.map((tx, index) => ( <li key={index}> {tx.recipient}: {tx.amount} </li> ))} </ul> <div style={buttonContainerStyle}> <button style={confirmButtonStyle} onClick={confirmSendTokens}> Confirm </button> <button style={cancelButtonStyle} onClick={closeModal}> Cancel </button> </div> </div> </div> )} </div> ); }; const fixedModalStyle = { position: "fixed", top: "20%", left: "50%", transform: "translate(-50%, -20%)", backgroundColor: "white", padding: "20px", boxShadow: "0 0 10px rgba(0, 0, 0, 0.3)", zIndex: 1000, }; const fixedModalContentStyle = { display: "flex", flexDirection: "column", alignItems: "center", }; const buttonContainerStyle = { display: "flex", justifyContent: "space-between", width: "100%", }; const confirmButtonStyle = { backgroundColor: "green", color: "white", padding: "10px 20px", border: "none", borderRadius: "5px", cursor: "pointer", marginRight: "10px", }; const cancelButtonStyle = { backgroundColor: "red", color: "white", padding: "10px 20px", border: "none", borderRadius: "5px", cursor: "pointer", }; return <MultiSenderWidget />;