Last active
October 3, 2022 06:16
-
-
Save nikogu/5df49f2743d8b98eadb9fe9a90deb0f9 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// contracts/AppNTF.sol | |
// SPDX-License-Identifier: MIT | |
pragma solidity ^0.8.4; | |
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol"; | |
import "@openzeppelin/contracts/utils/Counters.sol"; | |
contract AppNFT is ERC721URIStorage { | |
using Counters for Counters.Counter; | |
Counters.Counter private _tokenIds; | |
mapping(uint256 => string) public _appNameMap; | |
constructor() ERC721("BitForest", "BFT") {} | |
function add(address sender, string memory tokenURI, string memory name) public returns (uint256) { | |
uint256 newItemId = _tokenIds.current(); | |
bool hasSameName = false; | |
bool hasSameTokenURI = false; | |
for (uint i = 0; i < newItemId; i++) { | |
if (keccak256(abi.encodePacked(_appNameMap[i])) == keccak256(abi.encodePacked(name))) { | |
hasSameName = true; | |
break; | |
} | |
if (_exists(i) && keccak256(abi.encodePacked(this.tokenURI(i))) == keccak256(abi.encodePacked(tokenURI))) { | |
hasSameTokenURI = true; | |
break; | |
} | |
} | |
require(!hasSameName, "There is already a app of the same name"); | |
require(!hasSameTokenURI, "There is already a app of the same tokenURI"); | |
_mint(sender, newItemId); | |
_setTokenURI(newItemId, tokenURI); | |
_appNameMap[newItemId] = name; | |
_tokenIds.increment(); | |
return newItemId; | |
} | |
function currentCount() public view returns (uint256) { | |
return _tokenIds.current(); | |
} | |
function getName(uint256 tokenId) public view returns (string memory) { | |
return _appNameMap[tokenId]; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// contracts/AppStore.sol | |
// SPDX-License-Identifier: MIT | |
pragma solidity ^0.8.4; | |
import "./AppNFT.sol"; | |
contract AppStore { | |
AppNFT public appNTF; | |
/** | |
* App Property | |
* @price: The price of app / wei | |
* @seller: Who sell this app | |
* @buyers: Who buy this app | |
*/ | |
struct AppProperty { | |
uint price; | |
address payable seller; | |
address[] buyers; | |
mapping(address => bool) buyersMap; | |
} | |
/** | |
* AppNTF `TokenId(uint256)` => `AppProperty` | |
*/ | |
mapping(uint256 => AppProperty) public appMap; | |
// events | |
event OnSell(address seller, uint256 tokenId, string name, uint price); | |
event OnBuy(address buyer, address seller, uint256 tokenId, uint price); | |
event OnVerify(bool verified, uint256 tokenId); | |
constructor() { | |
appNTF = new AppNFT(); | |
} | |
/** | |
* Get the NFT item count | |
*/ | |
function totalCount() public view returns (uint256) { | |
return appNTF.currentCount(); | |
} | |
/** | |
* Get the NFT tokenURI | |
*/ | |
function getTokenURI(uint256 tokenId) public view returns (string memory) { | |
return appNTF.tokenURI(tokenId); | |
} | |
/** | |
* Get the App Name | |
*/ | |
function getAppName(uint256 tokenId) public view returns (string memory) { | |
return appNTF.getName(tokenId); | |
} | |
/** | |
* Get the App Seller | |
*/ | |
function getAppSeller(uint256 tokenId) public view returns (address) { | |
return appMap[tokenId].seller; | |
} | |
/** | |
* Get the App Price | |
*/ | |
function getAppPrice(uint256 tokenId) public view returns (uint) { | |
return appMap[tokenId].price; | |
} | |
/** | |
* Get the App Buyers | |
*/ | |
function getAppBuyers(uint256 tokenId) public view returns (address[] memory buyers) { | |
return appMap[tokenId].buyers; | |
} | |
/** | |
* The method developer use to publish app | |
*/ | |
// TODO: verify tokenURI unique | |
function sell(string memory name, string memory tokenURI, uint price) public returns (uint256) { | |
// create NTF token | |
uint ntfToken = appNTF.add(msg.sender, tokenURI, name); | |
// record app property: the price | |
appMap[ntfToken].seller = payable(msg.sender); | |
appMap[ntfToken].price = price; | |
emit OnSell(msg.sender, ntfToken, name, price); | |
return ntfToken; | |
} | |
/** | |
* The method consumers use to buy app | |
*/ | |
function buy(uint256 tokenId) public payable returns (bool) { | |
require(appMap[tokenId].seller != address(0), "Error: There is no app pointed to by this tokenId"); | |
require(appMap[tokenId].price == msg.value, "Error: The purchase price for this app is incorrect"); | |
require(appMap[tokenId].buyersMap[msg.sender] != true, "Error: This user has already purchased"); | |
// transform eth to seller | |
appMap[tokenId].seller.transfer(msg.value); | |
// add buyers to buyApp.buyers | |
appMap[tokenId].buyersMap[msg.sender] = true; | |
appMap[tokenId].buyers.push(msg.sender); | |
emit OnBuy(msg.sender, appMap[tokenId].seller, tokenId, msg.value); | |
return true; | |
} | |
/** | |
* The method developer use to verify consumer permissions | |
* | |
*/ | |
function verify(uint256 tokenId, address buyer) public returns (bool) { | |
require(appMap[tokenId].seller != address(0), "Error: There is no app pointed to by this tokenId"); | |
bool verified = appMap[tokenId].buyersMap[buyer] == true; | |
emit OnVerify(verified, tokenId); | |
return verified; | |
} | |
// Fallback: reverts if Ether is sent to this smart-contract by mistake | |
fallback () external { | |
revert(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment