Never stop doing what you love.
AVISO: TODAS LAS ADDRESS PRESENTADAS EN EL DISEÑO Y PROTOTIPO FUNCIONAL SON DE EJEMPLO, NO SE UTILIZA NINGUNA DE ESAS ADDRESS O WALLETS
Bitcoffee is a CrowdFunding Dapp on the RSK network, in which anyone can raise funds for their personal interests, campaigns, charity funds, etc as well as for their followers can follow their goals, this through the use of crypto assets such as RBTC, Stablecoins from RSK or our own token BITC (Bitcoffee Token).
This platform is now working at bitcoffee.site and every Smart Contract is fully functional and tested.
- Pitch
- Smart contract interactions
- Features
- Built with
- Workflow
- Roadmap
- Our Contracts
- Testing
- Screenshots
- Authors
- See our Demo
- Quick start
- Project Structure
Meet your goals through the realization of the claim of the contributions you make in your goals.
Start interacting with our platform through a wallet which we will teach you how to create step by step.
Start supporting a creator you follow by contributing to their goals which you can fund on our platform.
Set up your profile to start creating campaigns and interact with others in the platform
Learn how to refund your contributions made to goals that were not met.
Learn how to directly support your favorite creator through the direct contribution feature.
Launch your first goal to achieve your monetary goals through our platform which provides you with the tools to achieve it.
- 👁🗨 Pure design and dynamic views.
- 🦊 Connection with Metamask.
- 📱 Simple UI and a beautiful UX Design.
- 📡 RSK Testnet Network.
- 💳 Platform with own token (BITC).
- 🌐 Under the distributed IPFS network.
- ⛏ ERC-20 Tokens transactions on RSK Blockchain.
- VueJs - Vuejs is a JavaScript framework for building user interfaces.
- Web3.js - Web3.js is a collection of libraries that allow you to interact with a local or remote ethereum node using HTTP, IPC or WebSocket.
- BootstrapVue - Extensive list of components and Bundled Javascript plugins.
- Sanity.io - Sanity is the platform for structured content that powers remarkable digital experiences.
- Webpack - Webpack is a module bundler. Its main purpose is to bundle JavaScript files for usage in a browser, yet it is also capable of transforming, bundling, or packaging just about any resource or asset.
- Node.js -As an asynchronous event-driven JavaScript runtime, Node.js is designed to build scalable network applications.
In addition, we plan to create a subscription for users who want to contribute monthly to the creators. This is possible with the SDK of RIF to schedule transactions in RSK and offer plans for creators to upload exclusive content as a way to thank their followers for their support.
- Wireframes and UI.
- Branding.
- Initial structure.
- Fleek deploy.
- ERC-20 Token.
- Smart Contract deployed on RSK Testnet.
- Unit testing.
- Dapp v1 Launch.
- Smart contract for Crowdfunding.
- Rebranding essentials.
- rLogin implementation (Still in progress).
- Dapp v2 Launch.
- Leadboard for Direct Transactions: This component will list the top donators every month on each profile.
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.12;
contract Bitcoffee {
// Variables
string public name;
string public symbol;
uint8 public decimals;
uint256 public totalSupply;
mapping(address => uint256) public balanceOf;
mapping(address => mapping(address => uint256)) public allowance;
event Transfer(address indexed _from, address indexed _to, uint256 _value);
event Approval(address indexed _owner, address indexed _spender, uint256 _value);
// constructor
constructor(string memory _name, string memory _symbol, uint8 _decimals, uint256 _totalSupply) public {
name = _name;
symbol = _symbol;
decimals = _decimals;
totalSupply = _totalSupply;
balanceOf[msg.sender] = _totalSupply;
emit Transfer(address(0), msg.sender, _totalSupply);
}
// Metodos
function transfer(address _to, uint256 _value) public returns (bool success){
require(balanceOf[msg.sender] >= _value, "Not enough funds");
balanceOf[msg.sender] -= _value;
balanceOf[_to] += _value;
emit Transfer(msg.sender, _to, _value);
return true;
}
function approve(address _spender, uint256 _value) public returns (bool success){
allowance[msg.sender][_spender] = _value;
emit Approval(msg.sender, _spender, _value);
return true;
}
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success){
require(allowance[_from][msg.sender] >= _value);
require(balanceOf[_from] >= _value);
balanceOf[_from] -= _value;
allowance[_from][msg.sender] -= _value;
balanceOf[_to] += _value;
emit Transfer(_from, _to, _value);
return true;
}
}
This Smart Contract is tested with Truffle and is completely functional in the platform.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
interface IERC677 {
function transfer(address, uint) external returns (bool);
function transferFrom(
address,
address,
uint
) external returns (bool);
}
contract CrowdFundERC677 {
event Launch(
uint id,
address indexed creator,
uint goal,
string title,
string description,
uint32 startAt,
uint32 endAt,
string category
);
event Cancel(uint id);
event Pledge(uint indexed id, address indexed caller, uint amount);
event Unpledge(uint indexed id, address indexed caller, uint amount);
event Claim(uint id);
event Refund(uint id, address indexed caller, uint amount);
struct Campaign {
// Campaign id
uint id;
// Creator of campaign
address creator;
// Amount of tokens to raise
uint goal;
// Category goal
string category;
// Title for goal
string title;
// Desc in goal
string description;
// Total amount pledged
uint pledged;
// Timestamp of start of campaign
uint32 startAt;
// Timestamp of end of campaign
uint32 endAt;
// True if goal was reached and creator has claimed the tokens.
bool claimed;
}
IERC677 public immutable token;
// Total count of campaigns created.
// It is also used to generate id for new campaigns.
uint public count;
// Mapping from id to Campaign
mapping(uint => Campaign) public campaigns;
// Mapping from creator addres to Campaign
mapping(address => Campaign[]) public campaignsAddress;
// Mapping from campaign id => pledger => amount pledged
mapping(uint => mapping(address => uint)) public pledgedAmount;
// Mapping for campaings contributors
mapping(uint => address[]) public contributedCampaign;
constructor(address _token) {
token = IERC677(_token);
}
function launch(
uint _goal,
uint32 _startAt,
uint32 _endAt,
string memory _title,
string memory _description,
string memory _category
) external {
require(_startAt >= block.timestamp, "start at < now");
require(_endAt >= _startAt, "end at < start at");
require(_endAt <= block.timestamp + 90 days, "end at > max duration");
count += 1;
campaigns[count] = Campaign({
id: count,
creator: msg.sender,
goal: _goal,
title: _title,
description: _description,
pledged: 0,
startAt: _startAt,
endAt: _endAt,
claimed: false,
category: _category
});
campaignsAddress[msg.sender].push(Campaign({
id: count,
creator: msg.sender,
goal: _goal,
title: _title,
description: _description,
pledged: 0,
startAt: _startAt,
endAt: _endAt,
claimed: false,
category: _category
}));
contributedCampaign[count].push(msg.sender);
emit Launch(count, msg.sender, _goal, _title, _description, _startAt, _endAt, _category);
}
function creatorCamps(address _add) public view returns (uint) {
return campaignsAddress[_add].length;
}
function totalContributors(uint _camp) public view returns (uint) {
return contributedCampaign[_camp].length;
}
function cancel(uint _id) external {
Campaign memory campaign = campaigns[_id];
require(campaign.creator == msg.sender, "not creator");
require(block.timestamp < campaign.startAt, "started");
delete campaigns[_id];
emit Cancel(_id);
}
function pledge(uint _id, uint _amount) external {
Campaign storage campaign = campaigns[_id];
require(block.timestamp >= campaign.startAt, "not started");
require(block.timestamp <= campaign.endAt, "ended");
campaign.pledged += _amount;
pledgedAmount[_id][msg.sender] += _amount;
contributedCampaign[_id].push(msg.sender);
token.transferFrom(msg.sender, address(this), _amount);
emit Pledge(_id, msg.sender, _amount);
}
function unpledge(uint _id, uint _amount) external {
Campaign storage campaign = campaigns[_id];
require(block.timestamp <= campaign.endAt, "ended");
campaign.pledged -= _amount;
pledgedAmount[_id][msg.sender] -= _amount;
token.transfer(msg.sender, _amount);
emit Unpledge(_id, msg.sender, _amount);
}
function claim(uint _id) external {
Campaign storage campaign = campaigns[_id];
require(campaign.creator == msg.sender, "not creator");
require(block.timestamp > campaign.endAt, "not ended");
require(campaign.pledged >= campaign.goal, "pledged < goal");
require(!campaign.claimed, "claimed");
campaign.claimed = true;
token.transfer(campaign.creator, campaign.pledged);
emit Claim(_id);
}
function refund(uint _id) external {
Campaign memory campaign = campaigns[_id];
require(block.timestamp > campaign.endAt, "not ended");
require(campaign.pledged < campaign.goal, "pledged >= goal");
uint bal = pledgedAmount[_id][msg.sender];
pledgedAmount[_id][msg.sender] = 0;
token.transfer(msg.sender, bal);
emit Refund(_id, msg.sender, bal);
}
}
This Smart Contract is tested with Truffle and is completely functional in the platform. We followed this RSK Guide
- Create a campaign
- Cancel a campaign
- Pledge rRIF tokens
- Unpledge tokens
- Claim tokens from campaign
- Refund tokens from campaign
We used Truffle to test our Smart Contracts. Everything is working well ☕
- @srteerra - Angel Lopez
- @Guapura89 - Carlos Sanchez
- @jonocrod12 - Jonathan Ocampo
Here is what you need to run Bitcoffee locally:
- A Web Browser such Firefox or Google Chrome.
- Metamask extension.
- Node.js ^ 16.0.0
mkdir bitcoffee
cd bitcoffee/
git clone https://github.com/srteerra/bitcoffee.git
cd bitcoffee
npm install
Execute the following command:
npm run server
It may take a few minutes to set up the application, so stay calm!
http:/localhost:8080/
$ BitCoffee Tree
bitcoffee/
├── build:
│ └── contracts/: # Folder for Smart Contracts JSON.
├── migrations/:
│ ├── 1_initial_migration.js: # Initial migration.
│ └── 2_deploy_contracts.js: # Smart Contracts deploy.
├── contracts/:
| ├── Bitcoffee.sol: # Bitcoffee Smart Contract ERC-20 token.
│ ├── CrowdFund.sol: # CrowdFunding Smart Contract for Bitcoffee token.
│ ├── CrowdFundERC677.sol: # CrowdFunding Smart Contract for tRif.
│ └── Migrations.sol: # Migrations contract.
├── src/: # Folder for development content.
│ ├──app/: # Folder for Front-end.
│ │ ├──assets/: # Folder for project assets.
│ │ │ ├──icons/
│ │ │ ├──images/
│ │ │ ├──logos/
│ │ │ ├──vectors/
│ │ │ ├──breakpoints.scss: # File for Media Queries.
│ │ │ ├──globals.scss: # File for global styles.
│ │ │ ├──style.scss: # File for main styles.
│ │ │ └──variables.scss; # File for style variables.
│ │ ├──components/: # Folder for Vue components.
│ │ ├──router/:
│ │ │ └──index.js # File for router view.
│ │ ├──store/:
│ │ │ ├──actions.js # File for Vuex methods.
│ │ │ ├──getters.js # File for computed properties for stores.
│ │ │ ├──index.js
│ │ │ ├──mutations.js # File for state trasformations.
│ │ │ └──state.js # File for stored data.
│ │ ├──views/: # File for Views.
│ │ ├──App.vue:
│ │ ├──index.html: # Main HTML.
│ │ └──index.js:
│ ├──lib/: # Folder for local modules and tools.
│ └──app.js: # File to run the aplication.
├── studio/: # Sanity Folder.
├── test/: # Smart Contracts testing.
│ ├──Bitcoffee.js: # Testing for Bitcoffee Smart Contract.
│ ├──CrowdFund.js: # Testing for CrowdFund (Bitcoffee) Smart Contract.
│ └──CrowdFundERC677.js: # Testing for CrowdFund (tRIF) Smart Contract.
├── webpack.config.js # Webpack configurations for compile.
└── README.md: # Default README file.