#javascript #reactjs #solidity #web3 #truffle
Вопрос:
Я новичок в солидности и пытаюсь следовать некоторым учебным пособиям. У меня есть одностраничное приложение с поддержкой .файлы sol выполняют функции вставки и чтения.
Сценарий:
- Человек-1 вводит контент, и его успешно можно увидеть на интерфейсе.
- Люди могут дать немного ETH на содержание, но оно идет непосредственно по адресу контракта.
Как я могу изменить его, чтобы люди могли сообщать об этом автору контента?
Мой файл .sol:
//SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.6;
contract SocialNetwork {
string public name;
uint public postCount = 0;
mapping(uint => Post) public posts;
struct Post {
uint id;
string content;
uint tipAmount;
address payable author;
}
event PostCreated(
uint id,
string content,
uint tipAmount,
address payable author
);
event PostTipped(
uint id,
string content,
uint tipAmount,
address payable author
);
constructor() {
name = "Social Network";
}
function createPost(string memory _content) public {
// Require valid content
require(bytes(_content).length > 0);
// Increment the post count
postCount ;
// Create the post
posts[postCount] = Post(postCount, _content, 0, payable(msg.sender));
// Trigger event
emit PostCreated(postCount, _content, 0, payable(msg.sender));
}
function tipPost(uint _id) public payable {
// Make sure the id is valid
require(_id > 0 amp;amp; _id <= postCount);
// Fetch the post
Post memory _post = posts[_id];
// Fetch the author
address payable _author = _post.author;
// Pay the author by sending them Ether
payable(address(_author)).transfer(msg.value);
// Incremet the tip amount
_post.tipAmount = _post.tipAmount msg.value;
// Update the post
posts[_id] = _post;
// Trigger an event
emit PostTipped(postCount, _post.content, _post.tipAmount, _author);
}
}
Мой App.js файл:
import React, { Component } from 'react';
import Web3 from 'web3';
import './App.css';
import SocialNetwork from '../abis/SocialNetwork.json'
import Navbar from './Navbar'
import Main from './Main'
class App extends Component {
async componentWillMount() {
await this.loadWeb3()
await this.loadBlockchainData()
}
async loadWeb3() {
if (window.ethereum) {
window.web3 = new Web3(window.ethereum)
await window.ethereum.enable()
}
else if (window.web3) {
window.web3 = new Web3(window.web3.ethereum)
}
else {
window.alert('Non-Ethereum browser detected. You should consider trying MetaMask!')
}
}
async loadBlockchainData() {
const web3 = window.web3
// Load account
const accounts = await window.ethereum.request({method: 'eth_requestAccounts'})
this.setState({ account: accounts[0] })
// Network ID
const networkId = await web3.eth.net.getId()
const networkData = SocialNetwork.networks[networkId]
if(networkData) {
const socialNetwork = web3.eth.Contract(SocialNetwork.abi, networkData.address)
this.setState({ socialNetwork })
const postCount = await socialNetwork.methods.postCount().call()
this.setState({ postCount })
// Load Posts
for (var i = 1; i <= postCount; i ) {
const post = await socialNetwork.methods.posts(i).call()
this.setState({
posts: [...this.state.posts, post]
})
}
// Sort posts. Show highest tipped posts first
this.setState({
posts: this.state.posts.sort((a,b) => b.tipAmount - a.tipAmount )
})
this.setState({ loading: false})
} else {
window.alert('SocialNetwork contract not deployed to detected network.')
}
}
createPost(content) {
this.setState({ loading: true })
this.state.socialNetwork.methods.createPost(content).send({ from: this.state.account })
.once('receipt', (receipt) => {
this.setState({ loading: false })
})
.on('confirmation', function(confirmationNumber, receipt){
window.location.reload();
})
}
tipPost(id, tipAmount) {
this.setState({ loading: true })
//web3.eth.sendTransaction({from: this.state.account, to: _authorPay, value: tipAmount})
this.state.socialNetwork.methods.tipPost(id).send({ from: this.state.account, value: tipAmount })
.once('receipt', (receipt) => {
this.setState({ loading: false })
})
.on('confirmation', function(confirmationNumber, receipt){
window.location.reload();
})
}
constructor(props) {
super(props)
this.state = {
account: '',
socialNetwork: null,
postCount: 0,
posts: [],
loading: true
}
this.createPost = this.createPost.bind(this)
this.tipPost = this.tipPost.bind(this)
}
render() {
return (
<div>
<Navbar account={this.state.account} />
{ this.state.loading
? <div id="loader" className="text-center mt-5"><p>Loading...</p></div>
: <Main
posts={this.state.posts}
createPost={this.createPost}
tipPost={this.tipPost}
/>
}
</div>
);
}
}
export default App;
My Main.js file:
import React, { Component } from 'react';
import Identicon from 'identicon.js';
class Main extends Component {
render() {
return (
<div className="container-fluid mt-5">
<div className="row">
<main role="main" className="col-lg-12 ml-auto mr-auto" style={{ maxWidth: '500px' }}>
<div className="content mr-auto ml-auto">
<p>amp;nbsp;</p>
<form onSubmit={(event) => {
event.preventDefault()
const content = this.postContent.value
this.props.createPost(content)
}}>
<div className="form-group mr-sm-2">
<input
id="postContent"
type="text"
ref={(input) => { this.postContent = input }}
className="form-control"
placeholder="What's on your mind?"
required />
</div>
<button type="submit" className="btn btn-primary btn-block">Share</button>
</form>
<p>amp;nbsp;</p>
{ this.props.posts.map((post, key) => {
return(
<div className="card mb-4" key={key} >
<div className="card-header">
<img
alt="Avatar"
className='mr-2'
width='30'
height='30'
src={`data:image/png;base64,${new Identicon(post.author, 30).toString()}`}
/>
<small className="text-muted">{post.author}</small>
</div>
<ul id="postList" className="list-group list-group-flush">
<li className="list-group-item">
<p>{post.content}</p>
</li>
<li key={key} className="list-group-item py-2">
<small className="float-left mt-1 text-muted">
TIPS: {window.web3.utils.fromWei(post.tipAmount.toString(), 'Ether')} ETH
</small>
<button
className="btn btn-link btn-sm float-right pt-0"
name={post.id}
onClick={(event) => {
let tipAmount = window.web3.utils.toWei('0.1', 'Ether')
this.props.tipPost(event.target.name, tipAmount)
}}
>
TIP 0.1 ETH
</button>
</li>
</ul>
</div>
)
})}
</div>
</main>
</div>
</div>
);
}
}
export default Main;
I can send the tip to the author via the code below but I’d like to perform this action via using «this.state.socialNetwork.methods.tipPost()» function.
//web3.eth.sendTransaction({from: this.state.account, to: _authorPay, value: tipAmount})