BUILDING AN E-COMMERCE SHOPPING SMART CONTRACT

This is a guide to build an E-commerce shopping smart contract that involves buying and selling goods or services. So mainly it has buyers and sellers.

In this tutorial, we will go through how to create, deploy and interact with an e-commerce shopping smart contract on Gather Testnet.

Here we will use MetaMask as our wallet and remix IDE to compile and deploy our smart contract. You can use a different wallet and other frameworks like Hardhat or Truffle as well.

PREREQUISITES

  • MetaMask wallet configured with Gather testnet

  • Testnet GTHs. You can use Gather Faucet to get some testnet GTH.

STEP - 1: Setting up the contract file

Create a new file on Remix Ecom.sol and create a new contract shopping

STEP - 2: Registering as Seller and Paying the owner a fee of 1000 Wei

Create a Public address variable owner and made deployer address as owner in the constructor.

Use address mappings pointing to our struct seller. Here seller struct consists of all required details about the seller.

Add a method sellerSignup to check if the seller is already registered and check if msg.value along with the function is equal to 1000 Wei or not.

// SPDX-License-Identifier: MIT
pragma solidity ^0.5.4;
contract shopping {
    
   address payable public owner;
   
   constructor() public {
       owner=msg.sender;
          }
   struct seller {
     string name;
     address addr;
     uint bankGuaraantee;
     bool bgPaid;
     }
 mapping(address=> seller) public sellers;
 
  function sellerSignUp(string memory _name) public payable{
    require(!sellers[msg.sender].bgPaid);
        require(msg.value==1000 wei, "Bank Guarantee of 1000 wei Required");
        owner.transfer(msg.value);
        sellers[msg.sender].name= _name;
        sellers[msg.sender].addr= msg.sender;
        sellers[msg.sender].bankGuaraantee = msg.value;
        sellers[msg.sender].bgPaid=true;
    }
}

STEP - 3: List Product With All Required Details

Add a struct product with all required variables and made string mapping to the struct, so that you can update or buy Product with productId String

Add a function to check whether the seller paid the bank guarantee or not and to check if a product with the same productId is active already.

// SPDX-License-Identifier: MIT
pragma solidity ^ 0.5 .4;
contract shopping {

	address payable public owner;

	constructor() public {
		owner = msg.sender;
	}
	struct seller {
		string name;
		address addr;
		uint bankGuaraantee;
		bool bgPaid;
	}
	struct product {
		string productId;
		string productName;
		string Category;
		uint price;
		string description;
		address payable seller;
		bool isActive;
	}
	mapping(address => seller) public sellers;
	mapping(string => product) products;
	product[] public allProducts;

	function sellerSignUp(string memory _name) public payable {
		require(!sellers[msg.sender].bgPaid);
		require(msg.value == 1000 wei, "Bank Guarantee of 1000 wei Required");
		owner.transfer(msg.value);
		sellers[msg.sender].name = _name;
		sellers[msg.sender].addr = msg.sender;
		sellers[msg.sender].bankGuaraantee = msg.value;
		sellers[msg.sender].bgPaid = true;
	}

	function addProduct(string memory _productId, string memory _productName, string memory _category, uint _price, string memory _description) public {
		require(!products[_productId].isActive);
		require(sellers[msg.sender].bgPaid);

		product memory product = product(_productId, _productName, _category, _price, _description, msg.sender, true);
		products[_productId].productId = _productId;
		products[_productId].productName = _productName;
		products[_productId].Category = _category;
		products[_productId].description = _description;
		products[_productId].price = _price;
		products[_productId].seller = msg.sender;
		products[_productId].isActive = true;
		allProducts.push(product);

	}
}

STEP - 4: Track Orders Placed By Buyers

Add a struct ordersPlaced with required Tracking Detail variables and mapped struct array with seller address.

Pushed Order details to map sellerOrders when buyer placed an order.

Track Orders Placed by buyers with purchaseId

// SPDX-License-Identifier: MIT
pragma solidity ^ 0.5 .4;
contract shopping {

	address payable public owner;

	constructor() public {
		owner = msg.sender;
	}
	struct seller {
		string name;
		address addr;
		uint bankGuaraantee;
		bool bgPaid;
	}
	struct product {
		string productId;
		string productName;
		string Category;
		uint price;
		string description;
		address payable seller;
		bool isActive;
	}
	struct ordersPlaced {
		string productId;
		uint purchaseId;
		address orderedBy;
	}
	mapping(address => seller) public sellers;
	mapping(string => product) products;
	product[] public allProducts;
	mapping(address => ordersPlaced[]) sellerOrders;

	function sellerSignUp(string memory _name) public payable {
		require(!sellers[msg.sender].bgPaid);
		require(msg.value == 1000 wei, "Bank Guarantee of 1000 wei Required");
		owner.transfer(msg.value);
		sellers[msg.sender].name = _name;
		sellers[msg.sender].addr = msg.sender;
		sellers[msg.sender].bankGuaraantee = msg.value;
		sellers[msg.sender].bgPaid = true;
	}

	function addProduct(string memory _productId, string memory _productName, string memory _category, uint _price, string memory _description) public {
		require(!products[_productId].isActive);
		require(sellers[msg.sender].bgPaid);

		product memory product = product(_productId, _productName, _category, _price, _description, msg.sender, true);
		products[_productId].productId = _productId;
		products[_productId].productName = _productName;
		products[_productId].Category = _category;
		products[_productId].description = _description;
		products[_productId].price = _price;
		products[_productId].seller = msg.sender;
		products[_productId].isActive = true;
		allProducts.push(product);

	}

	function getOrdersPlaced(uint _index) public view returns(string memory, uint, address, string memory) {
		return (sellerOrders[msg.sender][_index].productId, sellerOrders[msg.sender][_index].purchaseId, sellerOrders[msg.sender][_index].orderedBy, sellerShipments[msg.sender][sellerOrders[msg.sender][_index].purchaseId].shipmentStatus);
	}

	function getShipmentDetails(uint _purchaseId) public view returns(string memory, string memory, address, string memory) {

		return (sellerShipments[msg.sender][_purchaseId].productId, sellerShipments[msg.sender][_purchaseId].shipmentStatus, sellerShipments[msg.sender][_purchaseId].orderedBy, sellerShipments[msg.sender][_purchaseId].deliveryAddress);
	}
}

STEP - 5: Ship Products And Update Shipment Details

Create a Struct sellerShipment with all required variables for Tracking and Updating Details and mapped this struct to address and nested uint.

Every seller can update shipment details with unique purchaseId

Update Shipment details with function updateShipments with purchaseId

// SPDX-License-Identifier: MIT
pragma solidity ^ 0.5 .4;
contract shopping {

	address payable public owner;

	constructor() public {
		owner = msg.sender;
	}
	struct seller {
		string name;
		address addr;
		uint bankGuaraantee;
		bool bgPaid;
	}
	struct product {
		string productId;
		string productName;
		string Category;
		uint price;
		string description;
		address payable seller;
		bool isActive;
	}
	struct ordersPlaced {
		string productId;
		uint purchaseId;
		address orderedBy;
	}
	struct sellerShipment {
		string productId;
		uint purchaseId;
		string shipmentStatus;
		string deliveryAddress;
		address payable orderedBy;
		bool isActive;
		bool isCanceled;
	}
	mapping(address => seller) public sellers;
	mapping(string => product) products;
	product[] public allProducts;
	mapping(address => ordersPlaced[]) sellerOrders;
	mapping(address => mapping(uint => sellerShipment)) sellerShipments;

	function sellerSignUp(string memory _name) public payable {
		require(!sellers[msg.sender].bgPaid);
		require(msg.value == 1000 wei, "Bank Guarantee of 1000 wei Required");
		owner.transfer(msg.value);
		sellers[msg.sender].name = _name;
		sellers[msg.sender].addr = msg.sender;
		sellers[msg.sender].bankGuaraantee = msg.value;
		sellers[msg.sender].bgPaid = true;
	}

	function addProduct(string memory _productId, string memory _productName, string memory _category, uint _price, string memory _description) public {
		require(!products[_productId].isActive);
		require(sellers[msg.sender].bgPaid);

		product memory product = product(_productId, _productName, _category, _price, _description, msg.sender, true);
		products[_productId].productId = _productId;
		products[_productId].productName = _productName;
		products[_productId].Category = _category;
		products[_productId].description = _description;
		products[_productId].price = _price;
		products[_productId].seller = msg.sender;
		products[_productId].isActive = true;
		allProducts.push(product);

	}

	function updateShipment(uint _purchaseId, string memory _shipmentDetails) public {
		require(sellerShipments[msg.sender][_purchaseId].isActive);

		sellerShipments[msg.sender][_purchaseId].shipmentStatus = _shipmentDetails;

	}

	function getOrdersPlaced(uint _index) public view returns(string memory, uint, address, string memory) {
		return (sellerOrders[msg.sender][_index].productId, sellerOrders[msg.sender][_index].purchaseId, sellerOrders[msg.sender][_index].orderedBy, sellerShipments[msg.sender][sellerOrders[msg.sender][_index].purchaseId].shipmentStatus);
	}

	function getShipmentDetails(uint _purchaseId) public view returns(string memory, string memory, address, string memory) {

		return (sellerShipments[msg.sender][_purchaseId].productId, sellerShipments[msg.sender][_purchaseId].shipmentStatus, sellerShipments[msg.sender][_purchaseId].orderedBy, sellerShipments[msg.sender][_purchaseId].deliveryAddress);
	}
}

STEP - 6: Refund Cancelled Orders

Create a function refund to check if Product with particular purchaseId is active or not, check if Buyer Cancelled Order or not and then check if seller Released amount equal to product price.

// SPDX-License-Identifier: MIT
pragma solidity ^ 0.5 .4;
contract shopping {

	address payable public owner;

	constructor() public {
		owner = msg.sender;
	}
	struct seller {
		string name;
		address addr;
		uint bankGuaraantee;
		bool bgPaid;
	}
	struct product {
		string productId;
		string productName;
		string Category;
		uint price;
		string description;
		address payable seller;
		bool isActive;
	}
	struct ordersPlaced {
		string productId;
		uint purchaseId;
		address orderedBy;
	}
	struct sellerShipment {
		string productId;
		uint purchaseId;
		string shipmentStatus;
		string deliveryAddress;
		address payable orderedBy;
		bool isActive;
		bool isCanceled;
	}
	mapping(address => seller) public sellers;
	mapping(string => product) products;
	product[] public allProducts;
	mapping(address => ordersPlaced[]) sellerOrders;
	mapping(address => mapping(uint => sellerShipment)) sellerShipments;

	function sellerSignUp(string memory _name) public payable {
		require(!sellers[msg.sender].bgPaid);
		require(msg.value == 1000 wei, "Bank Guarantee of 1000 wei Required");
		owner.transfer(msg.value);
		sellers[msg.sender].name = _name;
		sellers[msg.sender].addr = msg.sender;
		sellers[msg.sender].bankGuaraantee = msg.value;
		sellers[msg.sender].bgPaid = true;
	}

	function addProduct(string memory _productId, string memory _productName, string memory _category, uint _price, string memory _description) public {
		require(!products[_productId].isActive);
		require(sellers[msg.sender].bgPaid);

		product memory product = product(_productId, _productName, _category, _price, _description, msg.sender, true);
		products[_productId].productId = _productId;
		products[_productId].productName = _productName;
		products[_productId].Category = _category;
		products[_productId].description = _description;
		products[_productId].price = _price;
		products[_productId].seller = msg.sender;
		products[_productId].isActive = true;
		allProducts.push(product);

	}

	function updateShipment(uint _purchaseId, string memory _shipmentDetails) public {
		require(sellerShipments[msg.sender][_purchaseId].isActive);

		sellerShipments[msg.sender][_purchaseId].shipmentStatus = _shipmentDetails;

	}

	function getOrdersPlaced(uint _index) public view returns(string memory, uint, address, string memory) {
		return (sellerOrders[msg.sender][_index].productId, sellerOrders[msg.sender][_index].purchaseId, sellerOrders[msg.sender][_index].orderedBy, sellerShipments[msg.sender][sellerOrders[msg.sender][_index].purchaseId].shipmentStatus);
	}
	function refund(string memory _productId, uint _purchaseId)public payable {
       require (!sellerShipments[products[_productId].seller][purchaseId].isActive);
       require (sellerShipments[msg.sender[_purchaseId].isCanceled); 
       require(msg.value==products[_productId].price);
       sellerShipments[msg.sender[_purchaseId].orderedBy.transfer(msg.value);
sellerShipments[products[_productId].seller][_purchaseId].shipmentStatus= "Order Canceled By Buyer, Payment Refunded";
                    
     }
	function getShipmentDetails(uint _purchaseId) public view returns(string memory, string memory, address, string memory) {

		return (sellerShipments[msg.sender][_purchaseId].productId, sellerShipments[msg.sender][_purchaseId].shipmentStatus, sellerShipments[msg.sender][_purchaseId].orderedBy, sellerShipments[msg.sender][_purchaseId].deliveryAddress);
	}
}

STEP - 7: Create Buyer's Account

Create a Struct user with required user details and mapped it to address.

Add a function createAccount and pushed function arguments(user details) to the users mapping.

// SPDX-License-Identifier: MIT
pragma solidity ^ 0.5 .4;
contract shopping {

	address payable public owner;

	constructor() public {
		owner = msg.sender;
	}
	struct seller {
		string name;
		address addr;
		uint bankGuaraantee;
		bool bgPaid;
	}
	struct product {
		string productId;
		string productName;
		string Category;
		uint price;
		string description;
		address payable seller;
		bool isActive;
	}
	struct ordersPlaced {
		string productId;
		uint purchaseId;
		address orderedBy;
	}
	struct sellerShipment {
		string productId;
		uint purchaseId;
		string shipmentStatus;
		string deliveryAddress;
		address payable orderedBy;
		bool isActive;
		bool isCanceled;
	}
	struct user{
        string name;
        string email;
        string deliveryAddress;
        bool isCreated;
    }
	mapping(address => seller) public sellers;
	mapping(string => product) products;
	product[] public allProducts;
	mapping(address => ordersPlaced[]) sellerOrders;
	mapping(address => mapping(uint => sellerShipment)) sellerShipments;

	function sellerSignUp(string memory _name) public payable {
		require(!sellers[msg.sender].bgPaid);
		require(msg.value == 1000 wei, "Bank Guarantee of 1000 wei Required");
		owner.transfer(msg.value);
		sellers[msg.sender].name = _name;
		sellers[msg.sender].addr = msg.sender;
		sellers[msg.sender].bankGuaraantee = msg.value;
		sellers[msg.sender].bgPaid = true;
	}
	function createAccount(string memory _name, string memory _email, string memory _deliveryAddress) public 	 {
        
        users[msg.sender].name= _name;
        users[msg.sender].email= _email;
        users[msg.sender].deliveryAddress= _deliveryAddress;
        users[msg.sender].isCreated= true;
     }
	function addProduct(string memory _productId, string memory _productName, string memory _category, uint _price, string memory _description) public {
		require(!products[_productId].isActive);
		require(sellers[msg.sender].bgPaid);

		product memory product = product(_productId, _productName, _category, _price, _description, msg.sender, true);
		products[_productId].productId = _productId;
		products[_productId].productName = _productName;
		products[_productId].Category = _category;
		products[_productId].description = _description;
		products[_productId].price = _price;
		products[_productId].seller = msg.sender;
		products[_productId].isActive = true;
		allProducts.push(product);

	}

	function updateShipment(uint _purchaseId, string memory _shipmentDetails) public {
		require(sellerShipments[msg.sender][_purchaseId].isActive);

		sellerShipments[msg.sender][_purchaseId].shipmentStatus = _shipmentDetails;

	}

	function getOrdersPlaced(uint _index) public view returns(string memory, uint, address, string memory) {
		return (sellerOrders[msg.sender][_index].productId, sellerOrders[msg.sender][_index].purchaseId, sellerOrders[msg.sender][_index].orderedBy, sellerShipments[msg.sender][sellerOrders[msg.sender][_index].purchaseId].shipmentStatus);
	}
	function refund(string memory _productId, uint _purchaseId)public payable {
       require (!sellerShipments[products[_productId].seller][purchaseId].isActive);
       require (sellerShipments[msg.sender[_purchaseId].isCanceled); 
       require(msg.value==products[_productId].price);
       sellerShipments[msg.sender[_purchaseId].orderedBy.transfer(msg.value);
sellerShipments[products[_productId].seller][_purchaseId].shipmentStatus= "Order Canceled By Buyer, Payment Refunded";
                    
     }
	function getShipmentDetails(uint _purchaseId) public view returns(string memory, string memory, address, string memory) {

		return (sellerShipments[msg.sender][_purchaseId].productId, sellerShipments[msg.sender][_purchaseId].shipmentStatus, sellerShipments[msg.sender][_purchaseId].orderedBy, sellerShipments[msg.sender][_purchaseId].deliveryAddress);
	}
}

STEP - 8: Place A Order And Tracking Orders

// SPDX-License-Identifier: MIT
pragma solidity ^ 0.5 .4;
contract shopping {

	address payable public owner;

	constructor() public {
		owner = msg.sender;
	}
	struct seller {
		string name;
		address addr;
		uint bankGuaraantee;
		bool bgPaid;
	}
	struct product {
		string productId;
		string productName;
		string Category;
		uint price;
		string description;
		address payable seller;
		bool isActive;
	}
	struct ordersPlaced {
		string productId;
		uint purchaseId;
		address orderedBy;
	}
	struct sellerShipment {
		string productId;
		uint purchaseId;
		string shipmentStatus;
		string deliveryAddress;
		address payable orderedBy;
		bool isActive;
		bool isCanceled;
	}
	struct user{
        string name;
        string email;
        string deliveryAddress;
        bool isCreated;
    }
    struct orders{
        string productId;
        string orderStatus;
        uint purchaseId;
        string shipmentStatus;
    }
	mapping(address => seller) public sellers;
	mapping(string => product) products;
	product[] public allProducts;
	mapping(address => ordersPlaced[]) sellerOrders;
	mapping(address => mapping(uint => sellerShipment)) sellerShipments;
	mapping (address=>orders[]) userOrders;
	function sellerSignUp(string memory _name) public payable {
		require(!sellers[msg.sender].bgPaid);
		require(msg.value == 1000 wei, "Bank Guarantee of 1000 wei Required");
		owner.transfer(msg.value);
		sellers[msg.sender].name = _name;
		sellers[msg.sender].addr = msg.sender;
		sellers[msg.sender].bankGuaraantee = msg.value;
		sellers[msg.sender].bgPaid = true;
	}
	function createAccount(string memory _name, string memory _email, string memory _deliveryAddress) public 	 {
        
        users[msg.sender].name= _name;
        users[msg.sender].email= _email;
        users[msg.sender].deliveryAddress= _deliveryAddress;
        users[msg.sender].isCreated= true;
    }
    function buyProduct(string memory _productId)  public payable {
        
        require( users[msg.sender].isCreated);
        require(msg.value == products[_productId].price);
        
        
        products[_productId].seller.transfer(msg.value);
        
        purchaseId = id++;
		orders memory order = orders(_productId,  "Order Placed With Seller",purchaseId, 							sellerShipments[products[_productId].seller][purchaseId].shipmentStatus);
        userOrders[msg.sender].push(order);
        ordersPlaced memory ord = ordersPlaced(_productId, purchaseId, msg.sender);
        sellerOrders[products[_productId].seller].push(ord);

         sellerShipments[products[_productId].seller][purchaseId].productId=_productId;
         sellerShipments[products[_productId].seller][purchaseId].orderedBy=   msg.sender;
         sellerShipments[products[_productId].seller][purchaseId].purchaseId= purchaseId;
         sellerShipments[products[_productId].seller][purchaseId].deliveryAddress = 				users[msg.sender].deliveryAddress;
        sellerShipments[products[_productId].seller][purchaseId].isActive= true;
         }
         
        function myOrders (uint _index) public view returns(string memory, string memory, uint, string memory) {                
            return(userOrders[msg.sender][_index].productId, userOrders[msg.sender][_index].orderStatus, 				userOrders[msg.sender][_index].purchaseId, sellerShipments[products[userOrders[msg.sender]					[_index].productId].seller][userOrders[msg.sender][_index].purchaseId].shipmentStatus);                  } 
		function addProduct(string memory _productId, string memory _productName, string memory _category, 				uint _price, string memory _description) public {
			require(!products[_productId].isActive);
			require(sellers[msg.sender].bgPaid);

            product memory product = product(_productId, _productName, _category, _price, _description, 					msg.sender, true);
            products[_productId].productId = _productId;
            products[_productId].productName = _productName;
            products[_productId].Category = _category;
            products[_productId].description = _description;
            products[_productId].price = _price;
            products[_productId].seller = msg.sender;
            products[_productId].isActive = true;
            allProducts.push(product);
	}

	function updateShipment(uint _purchaseId, string memory _shipmentDetails) public {
		require(sellerShipments[msg.sender][_purchaseId].isActive);

		sellerShipments[msg.sender][_purchaseId].shipmentStatus = _shipmentDetails;

	}

	function getOrdersPlaced(uint _index) public view returns(string memory, uint, address, string memory) {
		return (sellerOrders[msg.sender][_index].productId, sellerOrders[msg.sender][_index].purchaseId, sellerOrders[msg.sender][_index].orderedBy, sellerShipments[msg.sender][sellerOrders[msg.sender][_index].purchaseId].shipmentStatus);
	}
	function refund(string memory _productId, uint _purchaseId)public payable {
       require (!sellerShipments[products[_productId].seller][purchaseId].isActive);
       require (sellerShipments[msg.sender[_purchaseId].isCanceled); 
       require(msg.value==products[_productId].price);
       sellerShipments[msg.sender[_purchaseId].orderedBy.transfer(msg.value);
sellerShipments[products[_productId].seller][_purchaseId].shipmentStatus= "Order Canceled By Buyer, Payment Refunded";
                    
     }
	function getShipmentDetails(uint _purchaseId) public view returns(string memory, string memory, address, string memory) {

		return (sellerShipments[msg.sender][_purchaseId].productId, sellerShipments[msg.sender][_purchaseId].shipmentStatus, sellerShipments[msg.sender][_purchaseId].orderedBy, sellerShipments[msg.sender][_purchaseId].deliveryAddress);
	}
}

STEP - 9: Cancelling An Order

Add a function to cancel an order it takes purchaseId as an argument and checks if the product with particular purchaseId is ordered by the current caller or not if the product with particular purchaseId is active or not.

// SPDX-License-Identifier: MIT
pragma solidity ^ 0.5 .4;
contract shopping {

	address payable public owner;

	constructor() public {
		owner = msg.sender;
	}
	struct seller {
		string name;
		address addr;
		uint bankGuaraantee;
		bool bgPaid;
	}
	struct product {
		string productId;
		string productName;
		string Category;
		uint price;
		string description;
		address payable seller;
		bool isActive;
	}
	struct ordersPlaced {
		string productId;
		uint purchaseId;
		address orderedBy;
	}
	struct sellerShipment {
		string productId;
		uint purchaseId;
		string shipmentStatus;
		string deliveryAddress;
		address payable orderedBy;
		bool isActive;
		bool isCanceled;
	}
	struct user{
        string name;
        string email;
        string deliveryAddress;
        bool isCreated;
    }
    struct orders{
        string productId;
        string orderStatus;
        uint purchaseId;
        string shipmentStatus;
    }
	mapping(address => seller) public sellers;
	mapping(string => product) products;
	product[] public allProducts;
	mapping(address => ordersPlaced[]) sellerOrders;
	mapping(address => mapping(uint => sellerShipment)) sellerShipments;
	mapping (address=>orders[]) userOrders;
	function sellerSignUp(string memory _name) public payable {
		require(!sellers[msg.sender].bgPaid);
		require(msg.value == 1000 wei, "Bank Guarantee of 1000 wei Required");
		owner.transfer(msg.value);
		sellers[msg.sender].name = _name;
		sellers[msg.sender].addr = msg.sender;
		sellers[msg.sender].bankGuaraantee = msg.value;
		sellers[msg.sender].bgPaid = true;
	}
	function createAccount(string memory _name, string memory _email, string memory _deliveryAddress) public 	 {
        
        users[msg.sender].name= _name;
        users[msg.sender].email= _email;
        users[msg.sender].deliveryAddress= _deliveryAddress;
        users[msg.sender].isCreated= true;
    }
    function buyProduct(string memory _productId)  public payable {
        
        require( users[msg.sender].isCreated);
        require(msg.value == products[_productId].price);
        
        
        products[_productId].seller.transfer(msg.value);
        
        purchaseId = id++;
		orders memory order = orders(_productId,  "Order Placed With Seller",purchaseId, 							sellerShipments[products[_productId].seller][purchaseId].shipmentStatus);
        userOrders[msg.sender].push(order);
        ordersPlaced memory ord = ordersPlaced(_productId, purchaseId, msg.sender);
        sellerOrders[products[_productId].seller].push(ord);

         sellerShipments[products[_productId].seller][purchaseId].productId=_productId;
         sellerShipments[products[_productId].seller][purchaseId].orderedBy=   msg.sender;
         sellerShipments[products[_productId].seller][purchaseId].purchaseId= purchaseId;
         sellerShipments[products[_productId].seller][purchaseId].deliveryAddress = 				users[msg.sender].deliveryAddress;
        sellerShipments[products[_productId].seller][purchaseId].isActive= true;
         }
         
        function myOrders (uint _index) public view returns(string memory, string memory, uint, string memory) {                
            return(userOrders[msg.sender][_index].productId, userOrders[msg.sender][_index].orderStatus, 				userOrders[msg.sender][_index].purchaseId, sellerShipments[products[userOrders[msg.sender]					[_index].productId].seller][userOrders[msg.sender][_index].purchaseId].shipmentStatus);                  } 
		function addProduct(string memory _productId, string memory _productName, string memory _category, 				uint _price, string memory _description) public {
			require(!products[_productId].isActive);
			require(sellers[msg.sender].bgPaid);

            product memory product = product(_productId, _productName, _category, _price, _description, 					msg.sender, true);
            products[_productId].productId = _productId;
            products[_productId].productName = _productName;
            products[_productId].Category = _category;
            products[_productId].description = _description;
            products[_productId].price = _price;
            products[_productId].seller = msg.sender;
            products[_productId].isActive = true;
            allProducts.push(product);
	}
	function cancelOrder(string memory _productId, uint _purchaseId)  public payable {
     require(sellerShipments[products[_productId].seller][_purchaseId].orderedBy==msg.sender, "Aww Crap.. You are not Authorized to This Product PurchaseId");
     require (sellerShipments[products[_productId].seller][purchaseId].isActive, "Aww crap..You Already Canceled This order"); 
    
    
  sellerShipments[products[_productId].seller][_purchaseId].shipmentStatus= "Order Canceled By Buyer, Payment will Be  Refunded";
 sellerShipments[products[_productId].seller][_purchaseId].isCanceled= true; 
    sellerShipments[products[_productId].seller][_purchaseId].isActive= false;
    }
	function updateShipment(uint _purchaseId, string memory _shipmentDetails) public {
		require(sellerShipments[msg.sender][_purchaseId].isActive);

		sellerShipments[msg.sender][_purchaseId].shipmentStatus = _shipmentDetails;

	}

	function getOrdersPlaced(uint _index) public view returns(string memory, uint, address, string memory) {
		return (sellerOrders[msg.sender][_index].productId, sellerOrders[msg.sender][_index].purchaseId, sellerOrders[msg.sender][_index].orderedBy, sellerShipments[msg.sender][sellerOrders[msg.sender][_index].purchaseId].shipmentStatus);
	}
	function refund(string memory _productId, uint _purchaseId)public payable {
       require (!sellerShipments[products[_productId].seller][purchaseId].isActive);
       require (sellerShipments[msg.sender[_purchaseId].isCanceled); 
       require(msg.value==products[_productId].price);
       sellerShipments[msg.sender[_purchaseId].orderedBy.transfer(msg.value);
sellerShipments[products[_productId].seller][_purchaseId].shipmentStatus= "Order Canceled By Buyer, Payment Refunded";
                    
     }
	function getShipmentDetails(uint _purchaseId) public view returns(string memory, string memory, address, string memory) {

		return (sellerShipments[msg.sender][_purchaseId].productId, sellerShipments[msg.sender][_purchaseId].shipmentStatus, sellerShipments[msg.sender][_purchaseId].orderedBy, sellerShipments[msg.sender][_purchaseId].deliveryAddress);
	}
}

The final Smart Contract

You can get the complete code from here as well - https://github.com/GatherNetwork/E-Commerce-Smart-Contract.git

// SPDX-License-Identifier: MIT
pragma solidity ^ 0.5 .4;
contract shopping {

	address payable public owner;

	constructor() public {
		owner = msg.sender;
	}
	uint id;
	uint purchaseId;
	struct seller {
		string name;
		address addr;
		uint bankGuaraantee;
		bool bgPaid;
	}
	struct product {
		string productId;
		string productName;
		string Category;
		uint price;
		string description;
		address payable seller;
		bool isActive;

	}
	struct ordersPlaced {
		string productId;
		uint purchaseId;
		address orderedBy;
	}
	struct sellerShipment {
		string productId;
		uint purchaseId;
		string shipmentStatus;
		string deliveryAddress;
		address payable orderedBy;
		bool isActive;
		bool isCanceled;
	}
	struct user {
		string name;
		string email;
		string deliveryAddress;
		bool isCreated;
	}
	struct orders {
		string productId;
		string orderStatus;
		uint purchaseId;
		string shipmentStatus;
	}
	mapping(address => seller) public sellers;
	mapping(string => product) products;
	product[] public allProducts;
	mapping(address => ordersPlaced[]) sellerOrders;
	mapping(address => mapping(uint => sellerShipment)) sellerShipments;
	mapping(address => user) users;
	mapping(address => orders[]) userOrders;

	function sellerSignUp(string memory _name) public payable {
		require(!sellers[msg.sender].bgPaid, "You are Already Registered");
		require(msg.value == 1000 wei, "Bank Guarantee of 1000 wei Required");
		owner.transfer(msg.value);
		sellers[msg.sender].name = _name;
		sellers[msg.sender].addr = msg.sender;
		sellers[msg.sender].bankGuaraantee = msg.value;
		sellers[msg.sender].bgPaid = true;
	}

	function createAccount(string memory _name, string memory _email, string memory _deliveryAddress) public {

		users[msg.sender].name = _name;
		users[msg.sender].email = _email;
		users[msg.sender].deliveryAddress = _deliveryAddress;
		users[msg.sender].isCreated = true;
	}

	function buyProduct(string memory _productId) public payable {


		require(msg.value == products[_productId].price, "Value Must be Equal to Price of Product");
		require(users[msg.sender].isCreated, "You Must Be Registered to Buy");

		products[_productId].seller.transfer(msg.value);

		purchaseId = id++;
		orders memory order = orders(_productId, "Order Placed With Seller", purchaseId, sellerShipments[products[_productId].seller][purchaseId].shipmentStatus);
		userOrders[msg.sender].push(order);
		ordersPlaced memory ord = ordersPlaced(_productId, purchaseId, msg.sender);
		sellerOrders[products[_productId].seller].push(ord);

		sellerShipments[products[_productId].seller][purchaseId].productId = _productId;
		sellerShipments[products[_productId].seller][purchaseId].orderedBy = msg.sender;
		sellerShipments[products[_productId].seller][purchaseId].purchaseId = purchaseId;
		sellerShipments[products[_productId].seller][purchaseId].deliveryAddress = users[msg.sender].deliveryAddress;
		sellerShipments[products[_productId].seller][purchaseId].isActive = true;
	}

	function addProduct(string memory _productId, string memory _productName, string memory _category, uint _price, string memory _description) public {
		require(sellers[msg.sender].bgPaid, "You are not Registered as Seller");
		require(!products[_productId].isActive, "Product With this Id is already Active. Use other UniqueId");


		product memory newProduct = product(_productId, _productName, _category, _price, _description, msg.sender, true);
		products[_productId].productId = _productId;
		products[_productId].productName = _productName;
		products[_productId].Category = _category;
		products[_productId].description = _description;
		products[_productId].price = _price;
		products[_productId].seller = msg.sender;
		products[_productId].isActive = true;
		allProducts.push(newProduct);

	}

	function cancelOrder(string memory _productId, uint _purchaseId) public payable {
		require(sellerShipments[products[_productId].seller][_purchaseId].orderedBy == msg.sender, "Aww Crap.. You are not Authorized to This Product PurchaseId");
		require(sellerShipments[products[_productId].seller][purchaseId].isActive, "Aww crap..You Already Canceled This order");


		sellerShipments[products[_productId].seller][_purchaseId].shipmentStatus = "Order Canceled By Buyer, Payment will Be  Refunded";
		sellerShipments[products[_productId].seller][_purchaseId].isCanceled = true;
		sellerShipments[products[_productId].seller][_purchaseId].isActive = false;
	}

	function updateShipment(uint _purchaseId, string memory _shipmentDetails) public {
		require(sellerShipments[msg.sender][_purchaseId].isActive, "Order is either inActive or cancelled");

		sellerShipments[msg.sender][_purchaseId].shipmentStatus = _shipmentDetails;

	}

	function refund(string memory _productId, uint _purchaseId) public payable {
		require(sellerShipments[msg.sender][_purchaseId].isCanceled, "Order is not Yet Cancelled");
		require(!sellerShipments[products[_productId].seller][purchaseId].isActive, "Order is Active and not yet Cancelled");
		require(msg.value == products[_productId].price, "Value Must be Equal to Product Price");
		sellerShipments[msg.sender][_purchaseId].orderedBy.transfer(msg.value);
		sellerShipments[products[_productId].seller][_purchaseId].shipmentStatus = "Order Canceled By Buyer, Payment Refunded";

	}

	function myOrders(uint _index) public view returns(string memory, string memory, uint, string memory) {
		return (userOrders[msg.sender][_index].productId, userOrders[msg.sender][_index].orderStatus, userOrders[msg.sender][_index].purchaseId, sellerShipments[products[userOrders[msg.sender][_index].productId].seller][userOrders[msg.sender][_index].purchaseId].shipmentStatus);
	}

	function getOrdersPlaced(uint _index) public view returns(string memory, uint, address, string memory) {
		return (sellerOrders[msg.sender][_index].productId, sellerOrders[msg.sender][_index].purchaseId, sellerOrders[msg.sender][_index].orderedBy, sellerShipments[msg.sender][sellerOrders[msg.sender][_index].purchaseId].shipmentStatus);
	}

	function getShipmentDetails(uint _purchaseId) public view returns(string memory, string memory, address, string memory) {

		return (sellerShipments[msg.sender][_purchaseId].productId, sellerShipments[msg.sender][_purchaseId].shipmentStatus, sellerShipments[msg.sender][_purchaseId].orderedBy, sellerShipments[msg.sender][_purchaseId].deliveryAddress);
	}

}

STEP - 10

Select the solidity compiler version 0.5.4+ and compile the contract.

STEP - 11

In the environments, section select inject web3 and connect your MetaMask account with enough GTHs and deploy the contract. Confirm the MetaMask transaction.

STEP - 12

The contract is now deployed and now you can use the methods to interact with the contract.

You can deploy this contract to the Gather mainnet as well, you will just need to configure MetaMask with the Gather mainnet.

VIDEO

Last updated