Skip to content
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

Frontend #7

Closed
wants to merge 7 commits into from
Closed
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
21,948 changes: 21,948 additions & 0 deletions package-lock.json

Large diffs are not rendered by default.

11 changes: 0 additions & 11 deletions packages/hardhat/.env.example

This file was deleted.

240 changes: 240 additions & 0 deletions packages/hardhat/contracts/ArtistMarketPlace.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,240 @@
//SPDX-License-Identifier: MIT
pragma solidity 0.8.19;

import { IVRFCoordinatorV2Plus } from "@chainlink/contracts/src/v0.8/vrf/dev/interfaces/IVRFCoordinatorV2Plus.sol";
import { VRFConsumerBaseV2Plus } from "@chainlink/contracts/src/v0.8/vrf/dev/VRFConsumerBaseV2Plus.sol";
import { VRFV2PlusClient } from "@chainlink/contracts/src/v0.8/vrf/dev/libraries/VRFV2PlusClient.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "hardhat/console.sol";

//75868828114239004182696661166274810031260136627899410775239615499108111680872

contract ArtistMarketPlace is ReentrancyGuard, VRFConsumerBaseV2Plus {
event RequestSent(uint256 requestId, uint32 numWords);
event RequestFulfilled(uint256 requestId, uint256[] randomWords);

error ErrorNoCommisionToWithdraw();
error ErrorArtWorkNotFound();
error ErrorAmountNotSufficientToBuyArtwork(
uint256 suppliedAmount,
uint256 costPrice
);
error ErrorIncompleteArtWorkDetails();
error ErrorArtistNotFound(address artistWallet);
error ErrorArtworkNotInTheSuppliedIndex();

enum ArtType {
AIGenerated,
HandDrawn
}

struct RequestStatus {
bool fulfilled; // whether the request has been successfully fulfilled
bool exists; // whether a requestId exists
uint256[] randomWords;
}

//wallet name style, number of arts , number of featured times

struct ArtWork {
string url;
ArtType artType;
uint256 cost;
uint256 likes;
address creator;
address owner;
}

struct Artist {
address wallet;
string name;
ArtType style;
uint256 numberoFArts;
uint256 numberFeaturedTimes;
uint256[] artworks;
}

mapping(uint256 => RequestStatus) public s_requests;
//artist address matched to artist commision held by the contract
mapping(address => uint256) public s_artistCommision;
//mapping of address to Artist array index
mapping(address => uint) public s_artistIndex;
//artwork
ArtWork[] public s_artworks;
Artist[] public s_artist;

//VRF Sepolia Chain
IVRFCoordinatorV2Plus COORDINATOR;
address vrfCoordinator = 0x5C210eF41CD1a72de73bF76eC39637bB0d3d7BEE;
//0x9DdfaCa8183c41ad55329BdeeD9F6A8d53168B1B;
bytes32 keyHash =
0xc799bd1e3bd4d1a41cd4968997a4e03dfd2a3c7c04b695881138580163f42887;

//0x787d74caea10b2b357790d5b5247c2f63d1d91572a9846f780606e4d953677ae;
uint32 callbackGasLimit = 2500000;
uint16 requestConfirmations = 3;
uint32 numWords = 1;

// State Variables
address private s_linkAddress;

// Your subscription ID.
uint256 public s_subscriptionId;
uint256[] public requestIds;
uint256 public lastRequestId;
uint256[] public lastRandomWords;

uint256 public featuredArtistIndex = 0;

modifier checkArtWorkDetails(ArtWork memory artwork) {
if (
bytes(artwork.url).length != 0 &&
artwork.cost > 0 &&
artwork.creator != address(0) &&
artwork.owner != address(0)
) {
_;
} else {
revert ErrorIncompleteArtWorkDetails();
}
}

constructor(uint256 subscriptionId) VRFConsumerBaseV2Plus(vrfCoordinator) {
COORDINATOR = IVRFCoordinatorV2Plus(vrfCoordinator);
s_subscriptionId = subscriptionId;
//create Text artist data here
_createTestArtist();
}

function getRandomWords() external returns (uint256 requestId) {
requestId = COORDINATOR.requestRandomWords(
VRFV2PlusClient.RandomWordsRequest({
keyHash: keyHash,
subId: s_subscriptionId,
requestConfirmations: requestConfirmations,
callbackGasLimit: callbackGasLimit,
numWords: numWords,
extraArgs: VRFV2PlusClient._argsToBytes(
VRFV2PlusClient.ExtraArgsV1({ nativePayment: false })
)
})
);
s_requests[requestId] = RequestStatus({
randomWords: new uint256[](0),
exists: true,
fulfilled: false
});
requestIds.push(requestId);
lastRequestId = requestId;
emit RequestSent(requestId, numWords);
return requestId;
}

function fulfillRandomWords(
uint256 _requestId,
uint256[] memory _randomWords
) internal override {
require(s_requests[_requestId].exists, "request not found");
s_requests[_requestId].fulfilled = true;
s_requests[_requestId].randomWords = _randomWords;
lastRandomWords = _randomWords;
featuredArtistIndex = lastRandomWords[0] % s_artist.length;
//increment the number of times artist was featured
if (s_artist[featuredArtistIndex].wallet != address(0)) {
s_artist[featuredArtistIndex].numberFeaturedTimes++;
}
emit RequestFulfilled(_requestId, _randomWords);
}

function displayArtistOfTheDay() public view returns (Artist memory) {
return s_artist[featuredArtistIndex];
}

function withdrawCommision() public payable nonReentrant {
uint256 commision = s_artistCommision[msg.sender];
if (commision > 0) {
//withdraw the commision from the contract
s_artistCommision[msg.sender] = 0;
(bool success, ) = payable(msg.sender).call{ value: commision }("");
require(success, "commision withdrawal failed");
}else{
revert ErrorNoCommisionToWithdraw();
}

}

function buyArtWork(uint256 artWorkIndex) public payable {
if ( artWorkIndex > s_artworks.length || s_artworks.length == 0 ){
revert ErrorArtworkNotInTheSuppliedIndex();
}
ArtWork memory artwork = s_artworks[artWorkIndex];
if (artwork.creator == address(0)) {
revert ErrorArtWorkNotFound();
}
if (msg.value < artwork.cost) {
revert ErrorAmountNotSufficientToBuyArtwork(
msg.value,
artwork.cost
);
}
//buy the art
s_artworks[artWorkIndex].owner = msg.sender;
s_artistCommision[artwork.creator] += msg.value;

}

function saveArtWorkDetails(
ArtWork memory artwork
) public checkArtWorkDetails(artwork) {
//save the artwork in the artwork storage
uint256 index = s_artworks.length;
s_artworks.push(artwork);
//update the artist works array with the artwork index
uint256 artistIndexInArray = s_artistIndex[artwork.creator];
Artist storage artist = s_artist[artistIndexInArray];
if (artist.wallet != artwork.creator) {
revert ErrorArtistNotFound(artwork.creator);
}
//we good save the index in the artist work array
uint256 artworkIndex = index == 0 ? index : index + 1;
artist.artworks.push(artworkIndex);
//s_artist[artistIndexInArray].artworks.push(artworkIndex);
//console.log("artist artwork length: ", s_artist[artistIndexInArray].artworks.length);
}

function getArtist(uint256 index) public view returns (Artist memory artist) {
return s_artist[index];
}

function _createTestArtist() private {
uint256[] memory artworks;
Artist memory artist1 = Artist({
name: "Jamie Bones",
wallet: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266,
style: ArtType.HandDrawn,
numberoFArts: 0,
numberFeaturedTimes: 0,
artworks: artworks
});
Artist memory artist2 = Artist({
name: "Jamie Foster",
wallet: 0x5cBEa346278d288207Fd4714E18551aF37441c15,
style: ArtType.AIGenerated,
numberoFArts: 0,
numberFeaturedTimes: 0,
artworks: artworks
});
//save the index in the mapping
s_artist.push(artist1);
s_artistIndex[0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266] =
s_artist.length -
1;
s_artist.push(artist2);
s_artistIndex[0x5cBEa346278d288207Fd4714E18551aF37441c15] =
s_artist.length -
1;
}

receive() external payable {}
}

2 changes: 2 additions & 0 deletions packages/hardhat/contracts/BuyMeACoffee.sol
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ contract BuyMeACoffee {
address payable public owner;
uint256 public price;
Memo[] public memos;



error InsufficientFunds();
error InvalidArguments(string message);
Expand Down
6 changes: 3 additions & 3 deletions packages/hardhat/deploy/00_deploy_your_contract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ const deployYourContract: DeployFunction = async function (hre: HardhatRuntimeEn
const { deployer } = await hre.getNamedAccounts();
const { deploy } = hre.deployments;

await deploy("YourContract", {
await deploy("ArtistMarketPlace", {
from: deployer,
// Contract constructor arguments
args: [deployer],
args: [2777],
log: true,
// autoMine: can be passed to the deploy function to make the deployment process faster on local networks by
// automatically mining the contract deployment transaction. There is no effect on live networks.
Expand All @@ -41,4 +41,4 @@ export default deployYourContract;

// Tags are useful if you have multiple deploy files and only want to run one of them.
// e.g. yarn deploy --tags YourContract
deployYourContract.tags = ["YourContract"];
deployYourContract.tags = ["ArtistMarketPlace"];
2 changes: 1 addition & 1 deletion packages/hardhat/hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const etherscanApiKey = process.env.ETHERSCAN_API_KEY || "DNXJA8RX2Q3VZ4URQIWP7Z

const config: HardhatUserConfig = {
solidity: {
version: "0.8.17",
version: "0.8.19",
settings: {
optimizer: {
enabled: true,
Expand Down
1 change: 1 addition & 0 deletions packages/hardhat/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
"typescript": "^5.1.6"
},
"dependencies": {
"@chainlink/contracts": "^1.1.0",
"@openzeppelin/contracts": "^4.8.1",
"@typechain/ethers-v6": "^0.5.1",
"dotenv": "^16.0.3",
Expand Down
11 changes: 10 additions & 1 deletion packages/hardhat/scripts/deployOptions.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import inquirer from "inquirer";
{ name: "Zora Sepolia", value: "zoraSepolia" },
{ name: "Lisk Sepolia", value: "liskSepolia" },
{ name: "Mode Sepolia", value: "modeSepolia" },
{ name: "Sepolia", value: "sepolia" },
{ name: "All the above", value: "all" },
{ name: "Others (specify)", value: "others" }, // Add this line
],
Expand All @@ -30,7 +31,15 @@ import inquirer from "inquirer";
},
]);

let allNetworks = ["hardhat", "optimismSepolia", "baseSepolia", "zoraSepolia", "liskSepolia", "modeSepolia"];
let allNetworks = [
"hardhat",
"optimismSepolia",
"baseSepolia",
"zoraSepolia",
"liskSepolia",
"modeSepolia",
"sepolia",
];
let selectedNetworks = answers.networks;

// Check if "all the above" is selected
Expand Down
Loading
Loading