Skip to content

social media app with redux #17

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions step33_web3_gatsby_examples/socialMediaPosts_app_redux/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# dependencies
/**/node_modules

# production
/frontend/build


# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/**/node_modules
/**/.pnp
/**/.pnp.js

# testing
/**/coverage

# production
/**/build

# misc
.DS_Store
.env
.env.local
.env.development.local
.env.test.local
.env.production.local

npm-debug.log*
yarn-debug.log*
yarn-error.log*
12 changes: 12 additions & 0 deletions step33_web3_gatsby_examples/socialMediaPosts_app_redux/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Social Media Posts Application

## backend
The backend of this application resides on a local blockchain (ganache). It can also be very easily deployed on a public network (described in the end readme file in backend folder).
The smart contracts were written in solidity using truffle

To understand and setup backend please go through the readme file in the backend folder

## frontend
The frontend of this application uses gatsby and web3js to connect with ganache through metamask.

To understand and setup frontend please go through the readme file in the frontend folder
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
# Setup (for deploying the contract on ganache)

### 1) go to the backend folder and install dependencies (yarn install or npm install)

### 2) download Ganache from https://www.trufflesuite.com/ganache

### 3) Open Ganache and go to settings. In settings click on the server tab and change the port number to 8545 (we are doing this because metamask allows us to easily connect to this port number)

>![ganacheSettings](imgs/ganacheSettings.png)

### 4) Open the truffle-config file and make sure that the network configuration is same as shown in the picture below. Here we are saying that we want to deploy our contracts to this network.
If you want to deploy your contracts to a public network you can change this network configuration.

You can also see that we are saving our contract artifacts in the frontend directory. We are doing this because we will be using some information from them in our frontend code.

>![ganacheSettings](imgs/truffleConfig.png)

### 5) Make sure you have a migration file for the Social Media contract in the migrations directory

### 6) Run 'truffle test' to see if all the tests are passing

### 7) Run 'truffle compile' to compile the contracts

### 8) Run 'truffle deploy' to the deploy the smart contracts to the blockchain

The code for the contract is in the contract's directory and the test directory contains the tests.


# Code Explanation


You will find the smart contract code in the 'contracts' directory
You can find the test for this smart contract in the test directory

We have 4 public state variables

1) postCount stores the total number of posts in the app (uint)
2) posts stores the information about the posts (mapping). for Ex. to get post with id 1 `posts[1]`
3) commentCount stores the total number of comments for each post (mapping). for Ex. to get number of comments on post with id 1 `commentCount[1]'
4) comments stores the information about the comments on each post (nested mapping). for Ex. to get the first comment on post with id 1 `comments[1][1]`
```


uint public postCount = 0;
mapping(uint => socialMediaPost) public posts;
mapping(uint => uint) public commentCount;
mapping(uint => mapping(uint => socialMediaComment)) public comments;

```

There are two functions in the contract. 1) createPost 2) createComment


The code for createPost function is shown below.

It only takes 1 input that is the text for the post. If the _text string is empty it throws an error.
It creates a post and stores it in the posts state variable and also emits an event
```

function createPost (string memory _text ) public {

require(bytes(_text).length > 0);

postCount++;

posts[postCount] = socialMediaPost(postCount,_text,msg.sender);
emit postCreated(postCount, _text, msg.sender);


}

```


The code for createComment function is shown below.

It only takes 2 inputs. The text for the comment and the postId.
This function also stores comments in the state variables and emits events
```

function createComment (string memory _text,uint _postId) public {

require(bytes(_text).length > 0);


require(_postId > 0 && _postId <= postCount);


commentCount[_postId]++;

comments[_postId][commentCount[_postId]] = socialMediaComment(commentCount[_postId],_text,msg.sender,_postId);
emit commentCreated(commentCount[_postId], _text, msg.sender, _postId);


}


```

Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.9.0;

contract Migrations {
address public owner = msg.sender;
uint public last_completed_migration;

modifier restricted() {
require(
msg.sender == owner,
"This function is restricted to the contract's owner"
);
_;
}

function setCompleted(uint completed) public restricted {
last_completed_migration = completed;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.9.0;

contract SocialMedia {

uint public postCount = 0;

mapping(uint => socialMediaPost) public posts;
mapping(uint => uint) public commentCount;
mapping(uint => mapping(uint => socialMediaComment)) public comments;


struct socialMediaPost {
uint id;
string text;
address postedBy;
}

struct socialMediaComment {
uint id;
string text;
address postedBy;
uint postId;
}

event postCreated(
uint id,
string text,
address postedBy
);

event commentCreated(
uint id,
string text,
address postedBy,
uint postId
);



function createPost (string memory _text ) public {

require(bytes(_text).length > 0);

postCount++;

posts[postCount] = socialMediaPost(postCount,_text,msg.sender);
emit postCreated(postCount, _text, msg.sender);


}


function createComment (string memory _text,uint _postId) public {

require(bytes(_text).length > 0);


require(_postId > 0 && _postId <= postCount);


commentCount[_postId]++;

comments[_postId][commentCount[_postId]] = socialMediaComment(commentCount[_postId],_text,msg.sender,_postId);
emit commentCreated(commentCount[_postId], _text, msg.sender, _postId);


}



}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const Migrations = artifacts.require("Migrations");

module.exports = function (deployer) {
deployer.deploy(Migrations);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const socialMedia = artifacts.require("socialMedia");

module.exports = function (deployer) {
deployer.deploy(socialMedia);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "test",
"version": "1.0.0",
"description": "",
"main": "socialMedia.test.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"dependencies": {
"chai": "^4.3.4",
"chai-as-promised": "^7.1.1",
"chai-bignumber": "^3.0.0"
},
"author": "",
"license": "ISC"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
const SocialMedia = artifacts.require('../contracts/socialMedia.sol')

require('chai')
.use(require('chai-as-promised'))
.should()

contract('SocialMedia', ([ user1, user2]) => {
let socialMedia

before(async () => {
socialMedia = await SocialMedia.deployed()
})

describe('deployment', async () => {
it('deploys successfully', async () => {
const address = await socialMedia.address
assert.notEqual(address, 0x0)
assert.notEqual(address, '')
assert.notEqual(address, null)
assert.notEqual(address, undefined)
})

})

describe('posts', async () => {
let result, postCount

before(async () => {
result = await socialMedia.createPost('helloWorld', { from: user1 })
postCount = await socialMedia.postCount()
})

it('creates post', async () => {
// SUCCESS
assert.equal(postCount, 1)
const event = result.logs[0].args
assert.equal(event.id.toNumber(), postCount.toNumber(), 'id is correct')
assert.equal(event.text, 'helloWorld', 'text is correct')
assert.equal(event.postedBy, user1, 'postedBy is correct')

// FAILURE: post must have some text
await socialMedia.createPost('', { from: user1 }).should.be.rejected;

})



})



describe('comments', async () => {
let result, comments, commentCount

before(async () => {
//product = await socialMedia.createPost('helloWorld', { from: user1 })
result = await socialMedia.createComment('helloWorldComment',1, { from: user2 });
comments = await socialMedia.comments(1,1);
commentCount = await socialMedia.commentCount(1);

})

it('creates comment', async () => {
// SUCCESS
assert.equal(comments.id, 1)
assert.equal(commentCount, 1)
const event = result.logs[0].args
assert.equal(event.text, 'helloWorldComment', 'text is correct')
assert.equal(event.postedBy, user2, 'postedBy is correct')
assert.equal(event.postId, 1, 'postId is correct')


// FAILURE: comment must have some text
await socialMedia.createComment('', 1, { from: user1 }).should.be.rejected;

// FAILURE: comment must have a valid postId
await socialMedia.createComment('helloWorldComment', 0, { from: user1 }).should.be.rejected;
await socialMedia.createComment('helloWorldComment', 2, { from: user1 }).should.be.rejected;
})



})



})
Loading