[
  {
    "path": "README.md",
    "content": "[![Documentation Status](https://readthedocs.org/projects/itpeople-blockchain-auction/badge/?version=latest)](http://itpeople-blockchain-auction.readthedocs.io/en/latest/?badge=latest)\r\n\r\n#Art Auction Blockchain Application\r\nCredits: Ratnakar Asara, Nishi Nidamarty, Ramesh Thoomu, Adam Gordon and Mohan Venkataraman\r\n\r\n**Disclaimer:** The images used in this sample PoC application have been downloaded from publicly available images on the internet, and the copyright belongs to the respective owners. The usage here is strictly for non-commercial purposes as sample data. We recommend that users create their own sample data as appropriate. All names, addresses and accounts numbers used in the sample data are fictitous. The information provided in this README.md is subject to change.\r\n\r\nAuction Chaincode is migrated to fabric v1.0 and these changes being tested on **fabric commit#** 5b59e0652f9edf5bd12a6ff7fd2e9991495190fe\r\n\r\n##Introduction\r\n\r\nThis Hyperledger/Fabric is an implementation of blockchain technology, leveraging familiar and proven technologies. It is a modular architecture allowing pluggable implementations of various function. It features powerful container technology to host any mainstream language for smart contracts development. Chaincode (smart contracts) or blockchain applications run on the fabric. Chaincode is written in Go language \r\n\r\nThe original intention of this application was to understand how to write a Go application on the Hyperledger/Fabric. This initial version was written to understand the different chaincode api's, the boundary that separates what goes into the blockchain and what lives within the enterprise application, usage of database features, error management etc. <br> </br>\r\n\r\n<img src=\"docs/images/auction_chain.png\" width=\"700\">\r\n## Application Description\r\n\r\nThis application deals with auctioning ART on the block chain. The blockchain makes sense here as there are many different stakeholders and can leverage the benefits of the \"Network Effect\". This application deals with the following stake holders:\r\n* Buyers and Sellers or Traders (TRD)\r\n* Banks (BNK)\r\n* Insurance Companies (INS)\r\n* Shipping and Forwarding (SHP)\r\n* Auction Houses (AH)\r\n* Art Dealers (DEL)\r\n* Artists (ART)\r\n\r\nThe typical business process is shown below\r\n![Business Process](docs/images/art_process.png)\r\n\r\n###Registering Stakeholder Accounts\r\n\r\nArtists, Traders, Dealers own **Assets** (Items). Auction Houses, Banks, Insurance Companies and Service Providers play a role in the auction process. To conduct business on the block chain, the stakeholder has to open an account on the block chain. In the production world, prior to opening an account, all of the stake-holder details may be authenticated by another blockchain like an IDaaS (Identity-as-a-Service). There are various stake holders as listed above, each with a different interest.\r\n\r\n###Registering Assets or Items\r\n\r\nThe Seller (Trader) who owns **Assets** must register the asset on the block chain in order to conduct business. When an **Asset** is submitted for registration, the chaincode does the following:\r\n   * Checks if the owner has a registered account\r\n   * Converts any presented \"Certificate of Authenticity\" or a credibly issued image to a byte stream, generates a key, encrypts the byte stream using the key and stores the image on the BC \r\n   * Provides the key to the **owner** for safe keeping and future reference\r\n   * Makes entries into the Item History so that the lifecycle of the Asset can be reviewed at any time\r\n\r\n###Making a Request to Auction an Asset\r\n\r\nWhen the owner of an Asset sees an opportunity to make money, they would like to auction the Asset. They engage an Auction House and make a **request to auction** the Asset. The request always specifies a **\"Reserve Price\"**. Sometimes, the owner may additionally specify a **\"Buy It Now\"** price as well. When the request is made, the item, owner and the auction house are all validated. (The chaincode simply validates that they are all registered on the BC).\r\n\r\nThe Auction House will most likely, behind the scene, get the Asset authenticated and determine the valuation before deciding to accept the item. One of the ways by which they could do some preliminary authentication is to request the **seller** to enter his **private key**, account-id and the registered item number into the client application. While the item number and account identifier is a straight validation, the key will be used to decrypt and retrieve the stored \"certificate of authenticity or image\". The state of the Auction is set to **INIT** at this point, until the Auction House is ready to **OPEN** the Asset for bids.\r\n\r\n###Opening the Auction for Bids\r\n\r\nThe Auction House will choose a time frame to place the item on auction and **OPEN** it up for accepting bids from potential Buyers. They may, if applicable, advertise the **BuyItNow** price.\r\n\r\n### \"Buy It Now\" and Accepting Bids\r\n\r\nDuring the window of the auction, potential buyers can place bids. If a Buyer wishes to exercise the \"Buy It Now\", they can buy the item right away provided there is no bid higher than the \"BuyItNow\" price.\r\n\r\nBids are accepted from buyers if\r\n   * The Bids have are equal or greater than the **Reserve Price\"**\r\n   * The auction is still **OPEN**\r\n   * The Buyer has a registered account\r\n\r\n### Buy It Now\r\n\r\nWhen a buyer chooses this option, the chain code does the following\r\n    * Validates the Buyer\r\n    * Checks if there are any bidders whose bid is higher than the **\"Buy It Now\"** price. If so, the offer is rejected\r\n    * If the **\"Buy It Now\"** price is applicable, it immediately **\"CLOSES\"** the auctions, creates a **transaction**\r\n    * It assigns the Asset to the new owner\r\n    * It also generates a new **Key**, re-encrypts the \"Certificate of Ownership or Image\", and provides the key to the new buyer\r\n    * The new price of the Asset is set to the **\"Buy It Now\"** price if not higher\r\n\r\n### Auction Expiry\r\n\r\nWhen the auction expires, the Auction House retrieves the highest bid and converts it to a **transaction** ( A transaction in the real world could mean creating insurance and shipping docs, collecting payments and commissions, issuing a new title or certificate to the new owner etc.), transfers ownership to the buyer and updates the price with the new **\"Hammer\"** price. It also generates a new **Key**, re-encrypts the \"Certificate of Ownership or Image\", and provides the key to the new buyer.\r\n\r\n### Transfer an Item to another User\r\n\r\nThe chain code supports this scenario, by allowing a **owner** of an Asset to transfer **\"ownership\"** to another person. The receiving person has to be registered on the block-chain. Currently the chain code does not execute any regulatory or compliance rules.\r\n\r\n### Validating Asset Ownership\r\n\r\nThe chain code supports this. In order to accomplish this, it does preliminary authentication by requesting the **seller** to enter his **private key**, account-id and the registered item number. While the item number and account identifier is a straight validation, the key will be used to decrypt and view the stored **\"Certificate of Authenticity or image\"**. If decryption fails, then it assumes that the owner is not the legal owner of the Asset.\r\n\r\n## APIs Available\r\nThe following Invoke and Query APIs are available from both CLI and REST, and have the following signature\r\n\r\n    func(stub *shim.ChaincodeStub, function string, args []string) ([]byte, error) \r\n\r\n### Invoke\r\n                * iPostUser \r\n                * iPostItem\r\n                * iPostAuctionRequest\r\n                * iPostTransaction\r\n                * iPostBid\r\n                * iOpenAuctionForBids\r\n                * iBuyItNow\r\n                * iTransferItem\r\n                * iCloseAuction\r\n                * iCloseOpenAuctions\r\n### Query\r\n                * qGetItem\r\n                * qGetUser\r\n                * qGetAuctionRequest\r\n                * qGetTransaction\r\n                * qGetBid\r\n                * qGetLastBid\r\n                * qGetHighestBid\r\n                * qGetNoOfBidsReceived\r\n                * qGetListOfBids\r\n                * qGetItemLog\r\n                * qGetItemListByCat\r\n                * qGetUserListByCat\r\n                * qGetListOfItemsOnAuc\r\n                * qGetListOfOpenAucs\r\n                * qValidateItemOwnership\r\n                * qIsItemOnAuction\r\n\r\n##Environment Setup\r\n\r\nPlease review instructions on setting up the [Development Environment](https://github.com/hyperledger/fabric/blob/master/docs/source/dev-setup/devenv.rst) as well as the setting up the [Sandbox Environment](https://github.com/hyperledger/fabric/blob/master/docs/source/Setup/Chaincode-setup.rst) to execute the chaincode.\r\n\r\n## Running the Application\r\n\r\n** Fork and clone the fabric**\r\n```\r\n git clone https://github.com/hyperledger/fabric.git\r\n cd $GOPATH/src/github.com/hyperledger/fabric\r\n Fork Auction git repository from here https://github.com/ITPeople-Blockchain/auction.git and clone from your remote auction repository\r\n git clone https://github.com/<username>/auction.git\r\n```\r\n\r\nExecute below command to clear production data \r\n\r\n`rm -rf /var/hyperledger/*`\r\n\r\n###Terminal 1\r\n\r\nBuild peer and Orderer binaries and Start Orderer\r\n\r\n```\r\n cd $GOPATH/src/github.com/hyperledger/fabric\r\n make native\r\n orderer\r\n```\r\n\r\n###Terminal 2\r\n\r\nStart Peer\r\n```\r\n cd $GOPATH/src/github.com/hyperledger/fabric\r\n peer node start -o 127.0.0.1:7050\r\n```\r\n###Terminal 3\r\n```\r\n cd $GOPATH/src/github.com/hyperledger/fabric/auction/art/scripts\r\n Run env.sh script to export CORE_PEER_MSPCONFIGPATH\r\n `source env.sh`\r\n```\r\n###Run the following shell scripts\r\n\r\nThe scripts are provided for the convenience of understanding how to use the application as well as testing in your specific cloned environment. The scripts execute all API calls in CLI mode. In CLI mode, the peer and the chaincode live within the same container. However, these scripts will not work well in NET mode. To test the application in NET mode, follow the instructions on using the UI to make the API calls.\r\n\r\n#### PostUsers\r\n\r\nThe PostUsers script inserts a set of users into the database. Today, the only validation done is to check if the user \r\nID is an integer.\r\nTODO: In a future version, the user identity will be validated against the IDaaS Blockchain prior to \r\ninserting into the database\r\n\r\n`./PostUsers`\r\n\r\n#### PostItems\r\n\r\nThe PostItems script inserts a set of ART ASSETS into the database. Before inserting the asset the chaincode checks \r\nif the CurrentOwner is registered as a User. Based on the image file name (in future this could be a title or some\r\nownership document) is retrieved and converted to a byte array ([]byte). An AES Key is generated, the byte array is encrypted\r\nand both key and the byte array are saved in the database.A log entry is made in the Item Log. \r\nPlease see code for detailed comments\r\n\r\n`./PostItems`\r\n\r\nIn the business process, the owner (User ID# 100) of the ASSET (Item# 1000) requests an entity like an Auction House (User ID# 200) to put the item on auction. Before Posting the auction request, the Asset is validated against the database. The Auction House ID is verified in the User Table. A log entry is made in the Item Log.\r\n\r\nTODO: In future, the owner of the asset will present his key to help with validation. \r\nThe AES key will be used to un-encrypt the stored image and authenticate ASSET ownership. \r\n\r\n#### PostAuctionRequest\r\n\r\nWhen the ASSET OWNER  of an item is ready to place his item on auction, he/she would identify an Auction House, determine what the reserve price should be and send a request to the Auction House expressing interest in placing their item on the auction block. \r\n\r\n`./PostAuctionRequest`\r\n\r\n#### OpenAuctionRequestForBids\r\n\r\nThe Auction House, we assume will inspect the physical item, the certificate of authenticity, the ownership key and other details. They would also run a valuation of the item to determine if the reserve price is valid. The application assumes these have occurred outside of the scope of the application\r\n\r\nEven though the ASSET OWNER has requested the Auction House to place the item on auction, the Auction is not yet open for acceptance of user bids. Hence any bid submitted against the item will be rejected if the auction is not open\r\nThis script opens the Auction Request for bids. It sets the status of the AuctionRequest to \"OPEN\". It opens a timer for \r\nthe duration of the auction which in the example is 3 minutes. During this window, any user can submit bids against the AuctionID. Once the timer expires, a script is created and saved called \"CloseAuction.sh\". The script gets triggered. \r\n\r\n##### CloseAuction\r\n\r\nThe CloseAuction.sh script invokes CloseAuction. \r\nCloseAuction will first change the status of the AuctionRequest to \"CLOSED\". It then fetches the highest bid from the list of bids received, and converts it to a Transaction. The transaction is posted, the ASSET is retrieved from the database, its price is set to the new Hammer Price and the CurrentOwner is set to the new buyer. The ASSET image is un-encrypted with the old key, a new Key is generated and the image is encrypted with the new key. The ASSET is updated in the database.\r\nAn log entry is made in the Item Log.\r\n\r\nTODO: In future, the Transaction will be a business document that triggers payments, shipping,insurance and commissions\r\n\r\n`./OpenAuctionRequestForBids`\r\n\r\nOpens the auction request for bids for 3 minutes - Auction Request ID used for testing is 1111 and Item 1000\r\nThis opens a timer for 3 minutes and once timer expires, writes a shell script to invoke CloseAuction...\r\n\r\nAs described above, once the auction is \"OPEN\", this script submits bids against that auctionID. Both the auctionID and the buyerID are validated before the bid is posted. Once the auction is \"CLOSED\", new bids will be rejected\r\n\r\n`./Submitbids`\r\n  submits a series of bids against auction# 1111 and item# 1000\r\n\r\n`./SubmitQueries`\r\n  This is list of queries that can be issued and must be used via cut and paste on command line (CLI)\r\n\r\nAfter the timer expires, the Close auction should get invoked and the highest bid should be posted as a transaction\r\n\r\n## Invoke APIs and usage\r\n**PostUser**:\r\n\r\n   This function is used to register an Account for any of the stakeholders defined earlier\r\n\r\n   **Usage (CLI mode)**\r\n\r\n   The call takes 9 arguments: User ID, Record Type, Name, Type, Address, Phone, Email, Bank Name, Account#, Routing#\r\n   \r\n   peer chaincode invoke -l golang -n mycc -c '{\"Function\": \"PostUser\", \"Args\":[\"100\", \"USER\", \"Ashley Hart\", \"TRD\",  \"Morrisville Parkway, #216, Morrisville, NC 27560\", \"9198063535\", \"ashley@itpeople.com\", \"SUNTRUST\", \"00017102345\", \"0234678\"]}'\r\n\r\n**PostItem**:\r\n\r\n   This function is used to register an Asset with the blockchain. The owner of the Asset must have a registered account prior to registering the Asset. No validation of the \"User Type\" is done by the chaincode and should be managed outside by the client. The name of the image (f6.png) is uploaded by the chaincode from a pre-determined directory, converted to []byte, encrypted using AES and stored in the blockchain.\r\n\r\n   **Usage (CLI mode)**\r\n\r\n   The call takes 12 arguments: Item ID, Record Type, Description, Detail, Date of Origin, Original or Reprint, Subject, Media, Size, Image File, Price, Current Owner ID\r\n   \r\n   peer chaincode invoke -l golang -n mycc -c '{\"Function\": \"PostItem\", \"Args\":[\"1400\", \"ARTINV\", \"Nature\", \"James Thomas\", \"19900115\", \"Original\", \"modern\", \"Water Color\", \"12 x 17 in\", \"f6.png\",\"1800\", \"100\"]}'\r\n\r\n**PostAuctionRequest**:\r\n\r\n   This function is used by the owner of an Asset to request an Auction House to accept the Asset for auction. The Auction House ID, the owner ID and the asset ID are all validated before a request can be posted. Posting a request does not mean bids can be accepted. The auction has to be opened in order for bids to be accepted or \"Buy It Now\" to happen.\r\n\r\n   **Usage (CLI mode)**\r\n\r\n   This call takes 11 argumnets: Auction ID, Record Type, Item ID, Auction House ID, Owner ID, Date of Request, Reserve Price, Buy-It-Now Price, Status, Dummy Open Date, Dummy Close Date\r\n   \r\n   peer chaincode invoke -l golang -n mycc -c '{\"Function\": \"PostAuctionRequest\", \"Args\":[\"1113\", \"AUCREQ\", \"1000\", \"200\", \"400\", \"04012016\", \"15000\", \"16000\", \"INIT\", \"2016-05-20 11:00:00.3 +0000 UTC\",\"2016-05-23 11:00:00.3 +0000 UTC\"]}'\r\n\r\n   The Auction Opendate and CloseDate are dummy dates and will be set when the auction is opened. The Auction ID must be unique and cannot be repeated. We assume that the client will generate a unique auction id prior to posting the request. The state of the Auction is \"INIT\" at this point.\r\n\r\n**OpenAuctionForBids**:\r\n\r\n   This function is assumed to be invoked by the role of \"Auction House\" which is one of the types of accounts registered using PostUser. It allows the auctioner to open an auction for bids. The auction request must be in \"INIT\" state to be \"OPEN\"ed. When the auction is opened for bids, both the open and close date and time are set. The following example opens the bid for 3 minutes. Auction open durations are currently provided in minutes to support testing.\r\n\r\n   **Usage (CLI mode)**\r\n\r\n   The call takes 3 arguments: Auction ID, Record Type, Duration in Minutes\r\n   \r\n   peer chaincode invoke -l golang -n mycc -c '{\"Function\": \"OpenAuctionForBids\", \"Args\":[\"1111\", \"OPENAUC\", \"3\"]}'\r\n\r\n**PostBid**:\r\n\r\n   This function allows a potential buyer to bid on the Asset once the auction is open. Every bid is checked for valid auction ID, asset ID and buyer ID. Bids must be higher than reserve price. Bids are accepted as long as the auction is \"OPEN\". Bid numbers must be unique and generated by the client.\r\n\r\n   **Usage (CLI mode)**\r\n\r\n   This call takes 6 arguments: Auction ID, Record Type, Bid Number, Item ID, Buyer ID, Buyer Offer Price\r\n   \r\n   peer chaincode invoke -l golang -n mycc -c '{\"Function\": \"PostBid\", \"Args\":[\"1111\", \"BID\", \"5\", \"1000\", \"400\", \"5000\"]}'\r\n\r\n**PostTransaction**:\r\n\r\n   Even though the Transaction is automatically generated and posted when one of the following events occur: \r\n   * Auction closes after the auction timer expires (Only CLI Mode)\r\n   * A message to close all expired auctions are close is issued by the client via \"CloseOpenAuctions\"\r\n   * A \"BuyItNow\" call is made which goes through \r\n   this function is exposed as a matter of convenience just in case transactions don't get posted properly. \r\n   When a Transaction is posted, it updates the Asset with the new buyer ID, re-generates a new key and encrypts the image/certificate and updates the asset price to the \"Hammer Price\". It also adds a new entry into the item history table.\r\n\r\n   **Usage (CLI mode)**\r\n\r\n   This call takes 8 arguments: Auction ID, Record Type, Item ID, Transaction Type, Buyer ID, Transaction Time, Hammer Time, Hammer Price\r\n   \r\n   peer chaincode invoke -l golang -n mycc -c '{\"Function\": \"PostBid\", \"Args\":[\"1111\", \"POSTTRAN\", \"1000\", \"SALE\",\"500\", \"2016-05-24 11:00:00\",\"2016-05-23 14:25:00\", \"12000\"]}'\r\n\r\n**BuyItNow**:\r\n\r\n   Sometimes, an asset owner can specify a \"Buy It Now\" price in addition to the \"Reserve Price\" while posting an auction request. If an asset has a \"Buy It Now\" price, a buyer can issue a \"BuyItNow\" call. If there are no bids higher than the \"BuyItNow\" price, the request will be rejected. If the request goes through, the auction is closed and a transaction is posted against the buyer. \r\n\r\n   **Usage (CLI mode)**\r\n\r\n   This call is similar to the PostBid, except the price is set to the Buy-It-Now price.\r\n\r\n   peer chaincode invoke -l golang -n mycc -c '{\"Function\": \"BuyItNow\", \"Args\":[\"1111\", \"BID\", \"1\", \"1000\", \"300\", \"1800\"]}'\r\n\r\n**TransferItem**:\r\n\r\n   At any time, the current owner of an asset can transfer the item at no additional cost or change in value to another user, provided the asset is not initiated for auctions, or is in the process of an auction. Smart contract rules may have to be written to comply with local regulations and taxes. The current owner has to prove ownership by providing his key. The owner id, item id and the key are all validated before transfer can take place. The new owner will receive a new key.\r\n\r\n   **Usage (CLI mode)**\r\n\r\n   This call takes 5 arguments: Item ID, Current Owner ID, Owner Key, Transferee ID, Record Type\r\n   \r\n   peer chaincode invoke -l golang -n mycc -c '{\"Function\": \"TransferItem\", \"Args\": [\"1000\", \"100\", \"218MC/ipIsIrDhE9TKXqG2NsWl7KSE59Y3UmwBzSrQo=\", \"300\", \"XFER\"]}'\r\n\r\n**CloseAuction**:\r\n\r\n   This function call closes an auction once the time expires. This call is automatically issued in \"CLI\" mode since the \"OpenAuctionForBids\" call triggers a go routine that sleeps for the duration of the auction and the automatically issues a \"CloseAuction\" call. This functions closes the auction request, picks the highest bid and creates a transaction an then posts the transaction.\r\n\r\n   **Usage (CLI mode)**\r\n\r\n   This call takes two arguments: Auction ID, Record Type\r\n   \r\n   peer chaincode invoke -l golang -n mycc -c '{\"Function\": \"CloseAuction\", \"Args\": [\"1111\",\"AUCREQ\"]}'\r\n\r\n**CloseOpenAuctions**:\r\n\r\n   This is a function designed specifically for Bluemix situations where the peer and the chaincode run in different containers, hence a call as shown in each of \"Usage (CLI mode)\" will not work. This function is issued periodically by the client (UI or applications consuming the blockchain) as a REST call. The functions checks for auctions whose time has run-out and closes them.\r\n\r\n   **Usage (CLI mode)**\r\n\r\n   This call takes two arguments: 2016, Record Type\r\n   \r\n   peer chaincode invoke -l golang -n mycc -c '{\"Function\": \"CloseOpenAuctions\", \"Args\": [\"2016\", \"CLAUC\"]}'\r\n\r\n###Query APIs and Usage\r\n\r\n**GetItem**:\r\n\r\n   Retrieves an Asset record by asset ID.\r\n\r\n   **Usage (CLI mode)**\r\n\r\n      peer chaincode query -l golang -n mycc -c '{\"Function\": \"GetItem\", \"Args\": [\"1000\"]}'\r\n \r\n**GetUser**:\r\n\r\n   Retrieves an user record by user or stakeholder ID.\r\n\r\n   **Usage (CLI mode)**\r\n\r\n      peer chaincode query -l golang -n mycc -c '{\"Function\": \"GetUser\", \"Args\": [\"100\"]}'\r\n   \r\n**GetAuctionRequest**:\r\n\r\n   Retrieves an auction request by auction request ID.\r\n\r\n   **Usage (CLI mode)**\r\n\r\n      peer chaincode query -l golang -n mycc -c '{\"Function\": \"GetAuctionRequest\", \"Args\": [\"1111\"]}'\r\n\r\n**GetTransaction**:\r\n\r\n   Retrieves an transaction posted against an auction by auction request ID and asset ID.\r\n\r\n   **Usage (CLI mode)**\r\n\r\n      peer chaincode query -l golang -n mycc -c '{\"Function\": \"GetTransaction\", \"Args\": [\"1111\", \"1000\"]}'\r\n\r\n**GetBid**:\r\n\r\n   Retrieves a single bid by auction ID and bid number\r\n\r\n   **Usage (CLI mode)**\r\n\r\n      peer chaincode query -l golang -n mycc -c '{\"Function\": \"GetBid\",  \"Args\": [\"1111\", \"5\"]}'\r\n   \r\n**GetLastBid**:\r\n\r\n   Retrieves the last submitted bid. Since bids are submitted in random , and the only requirement is that the bid price be higher than the reserve price, the last received bid need not be the highest bid.\r\n\r\n   **Usage (CLI mode)**\r\n\r\n      peer chaincode query -l golang -n mycc -c '{\"Function\": \"GetLastBid\",\"Args\": [\"1111\"]}'\r\n\r\n**GetHighestBid**:\r\n\r\n   Retrieves the highest bid submitted against the auction thus far. If the auction has expired, then the highest bid is the highest bid for the auction.\r\n\r\n   **Usage (CLI mode)**\r\n\r\n      peer chaincode query -l golang -n mycc -c '{\"Function\": \"GetHighestBid\", \"Args\": [\"1111\"]}'\r\n   \r\n**GetNoOfBidsReceived**:\r\n\r\n   Retrieves the total number of bids received at any point in time. If the auction has expired, it represents the total number of bids received against that auction.\r\n\r\n   **Usage (CLI mode)**\r\n\r\n      peer chaincode query -l golang -n mycc -c '{\"Function\": \"GetNoOfBidsReceived\", \"Args\": [\"1111\"]}'\r\n\r\n**GetListOfBids**:\r\n   \r\n   Retrieves all the bids received against an auction. each row in the list represents a bid object.\r\n\r\n   **Usage (CLI mode)**\r\n\r\n      peer chaincode query -l golang -n mycc -c '{\"Function\": \"GetListOfBids\", \"Args\": [\"1111\"]}'\r\n\r\n**GetItemLog**:\r\n\r\n   Retrieves the history of an asset. The log is updated when an asset is registered, put on auction, post auction, transfered etc.\r\n\r\n   **Usage (CLI mode)**\r\n\r\n      peer chaincode query -l golang -n mycc -c '{\"Function\": \"GetItemLog\",\"Args\": [\"1000\"]}'\r\n   \r\n**GetItemListByCat**:\r\n\r\n   Retrieves a list of assets by asset category. If only the first key is provided, the query retrieves all assets. \"2016\" is hard-coded as a fixed first key. This is a band-aid solution to retrieve all records. This is a band-aid solution to retrieve all records. The following query retrieves all assets of category \"modern\".\r\n\r\n   **Usage (CLI mode)**\r\n\r\n      peer chaincode query -l golang -n mycc -c '{\"Function\": \"GetItemListByCat\",\"Args\": [\"2016\", \"modern\"]}'\r\n\r\n**GetUserListByCat**:\r\n\r\n   Retrieves a list of stakeholders or account holders by stakeholder type. If only the first key is provided, the query retrieves all assets. \"2016\" is hard-coded as a fixed first key. This is a band-aid solution to retrieve all records. The following query retrieves all stakeholders of type \"AH\" or auction houses.\r\n\r\n   **Usage (CLI mode)**\r\n\r\n      peer chaincode query -l golang -n mycc -c '{\"Function\": \"GetItemListByCat\",\"Args\": [\"2016\", \"AH\"]}'\r\n\r\n**GetListOfInitAucs**:\r\n\r\n   This query retrieves all assets which have been submitted for auction. Their status is \"Init\". The \"2016\" is a fixed key to denote all auctions in 2016.\r\n\r\n   **Usage (CLI mode)**\r\n\r\n      peer chaincode query -l golang -n mycc -c '{\"Function\": \"GetListOfInitAucs\",\"Args\": [\"2016\"]}'\r\n   \r\n**GetListOfOpenAucs**:\r\n\r\n   This query retrieves a list of all assets whose auctions have been \"OPEN\"ed for receiving bids. The \"2016\" is a fixed key to denote all auctions in 2016.\r\n\r\n   **Usage (CLI mode)**\r\n\r\n      peer chaincode query -l golang -n mycc -c '{\"Function\": \"GetListOfOpenAucs\", \"Args\": [\"2016\"]}'\r\n   \r\n**ValidateItemOwnership**:\r\n\r\n   Validates the ownership of an asset. Checks for valid account id, asset id and retrieves asset from blockchain using the owners's key. The arguments are Item ID, Current Owner ID and Owner's Key.\r\n\r\n   **Usage (CLI mode)**\r\n\r\n      peer chaincode query -l golang -n mycc -c '{\"Function\": \"ValidateItemOwnership\",   \"Args\": [\"1000\", \"500\", \"avQX6JfTnELAY4mkRhOr8P7vmz0H3aAIuFGsGiSD5UQ=\"]}'\r\n\r\n**IsItemOnAuction**:\r\n\r\n   Checks whether an Asset has an **auction request** posted, or currently on auction and returns a boolean true or false.\r\n\r\n   **Usage (CLI mode)**\r\n\r\n      peer chaincode query -l golang -n mycc -c '{\"Function\": \"IsItemOnAuction\", \"Args\": [\"1999\", \"VERIFY\"]}'\r\n\r\n##Notes\r\n\r\n* Once an auction request is posted or an auction is open for bids, there is no api to remove the auction request or close the auction prematurely and rejecting all bids received\r\n* In the current version, the image is encrypted and stored in the blockchain. However, in future, it is envisioned that only the hash of the image  along with the URI to the location of the image will be saved\r\n\r\n##Runnning the Application using the Web Browser\r\n\r\nThe chaincode functions can be accessed via the browser, Please refer [auction-app](https://github.com/ITPeople-Blockchain/auction-app) for more details.\r\n"
  },
  {
    "path": "art/artchaincode/art_app.go",
    "content": "/******************************************************************\nCopyright IT People Corp. 2017 All Rights Reserved.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n                 http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n\n******************************************************************/\n\n///////////////////////////////////////////////////////////////////////\n// Author : IT People - Mohan - table API for v1.0\n// Enable CouchDb as the database..\n// Purpose: Explore the Hyperledger/fabric and understand\n// how to write an chain code, application/chain code boundaries\n// The code is not the best as it has just hammered out in a day or two\n// Feedback and updates are appreciated\n///////////////////////////////////////////////////////////////////////\n\npackage main\n\nimport (\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"itpUtils\"\n\t\"os\"\n        \"net/http\"\n        \"io\"\n\t\"runtime\"\n\t\"strconv\"\n\t\"time\"\n\n\t\"github.com/hyperledger/fabric/core/chaincode/shim\"\n\tpb \"github.com/hyperledger/fabric/protos/peer\"\n)\n\n///////////////////////////////////////////////////////////////////////////////////////\n// This creates a record of the Asset (Inventory)\n// Includes Description, title, certificate of authenticity or image whatever..idea is to checkin a image and store it\n// in encrypted form\n// Example:\n// Item { 113869, \"Flower Urn on a Patio\", \"Liz Jardine\", \"10102007\", \"Original\", \"Floral\", \"Acrylic\", \"15 x 15 in\", \"sample_9.png\",\"$600\", \"My Gallery }\n///////////////////////////////////////////////////////////////////////////////////////\n\ntype ItemObject struct {\n\tItemID         string\n\tRecType        string\n\tItemDesc       string\n\tItemDetail     string // Could included details such as who created the Art work if item is a Painting\n\tItemDate       string\n\tItemType       string\n\tItemSubject    string\n\tItemMedia      string\n\tItemSize       string\n\tItemPicFN      string\n\tItemImage      []byte // This has to be generated AES encrypted using the file name\n\tAES_Key        []byte // This is generated by the AES Algorithms\n\tItemImageType  string // should be used to regenerate the appropriate image type\n\tItemBasePrice  string // Reserve Price at Auction must be greater than this price\n\tCurrentOwnerID string // This is validated for a user registered record\n\tTimeStamp      string // This is the time stamp\n}\n\n////////////////////////////////////////////////////////////////////////////////\n// Has an item entry every time the item changes hands\n////////////////////////////////////////////////////////////////////////////////\ntype ItemLog struct {\n\tItemID       string // PRIMARY KEY\n\tStatus       string // SECONDARY KEY - OnAuc, OnSale, NA\n\tAuctionedBy  string // SECONDARY KEY - Auction House ID if applicable\n\tRecType      string // ITEMHIS\n\tItemDesc     string\n\tCurrentOwner string\n\tDate         string // Date when status changed\n}\n\n/////////////////////////////////////////////////////////////\n// Create Buyer, Seller , Auction House, Authenticator\n// Could establish valid UserTypes -\n// AH (Auction House)\n// TR (Buyer or Seller)\n// AP (Appraiser)\n// IN (Insurance)\n// BK (bank)\n// SH (Shipper)\n/////////////////////////////////////////////////////////////\ntype UserObject struct {\n\tUserID    string\n\tRecType   string // Type = USER\n\tName      string\n\tUserType  string // Auction House (AH), Bank (BK), Buyer or Seller (TR), Shipper (SH), Appraiser (AP)\n\tAddress   string\n\tPhone     string\n\tEmail     string\n\tBank      string\n\tAccountNo string\n\tRoutingNo string\n\tTimestamp string\n}\n\n/////////////////////////////////////////////////////////////////////////////\n// Register a request for participating in an auction\n// Usually posted by a seller who owns a piece of ITEM\n// The Auction house will determine when to open the item for Auction\n// The Auction House may conduct an appraisal and genuineness of the item\n/////////////////////////////////////////////////////////////////////////////\n\ntype AuctionRequest struct {\n\tAuctionID      string\n\tRecType        string // AUCREQ\n\tItemID         string\n\tAuctionHouseID string // ID of the Auction House managing the auction\n\tSellerID       string // ID Of Seller - to verified against the Item CurrentOwnerId\n\tRequestDate    string // Date on which Auction Request was filed\n\tReservePrice   string // reserver price > previous purchase price\n\tBuyItNowPrice  string // 0 (Zero) if not applicable else specify price\n\tStatus         string // INIT, OPEN, CLOSED (To be Updated by Trgger Auction)\n\tOpenDate       string // Date on which auction will occur (To be Updated by Trigger Auction)\n\tCloseDate      string // Date and time when Auction will close (To be Updated by Trigger Auction)\n\tTimeStamp      string // The transaction Date and Time\n}\n\n/////////////////////////////////////////////////////////////\n// POST the transaction after the Auction Completes\n// Post an Auction Transaction\n// Post an Updated Item Object\n// Once an auction request is opened for auctions, a timer is kicked\n// off and bids are accepted. When the timer expires, the highest bid\n// is selected and converted into a Transaction\n// This transaction is a simple view\n/////////////////////////////////////////////////////////////\n\ntype ItemTransaction struct {\n\tAuctionID   string\n\tRecType     string // POSTTRAN\n\tItemID      string\n\tTransType   string // Sale, Buy, Commission\n\tUserId      string // Buyer or Seller ID\n\tTransDate   string // Date of Settlement (Buyer or Seller)\n\tHammerTime  string // Time of hammer strike - SOLD\n\tHammerPrice string // Total Settlement price\n\tDetails     string // Details about the Transaction\n}\n\n////////////////////////////////////////////////////////////////\n//  This is a Bid. Bids are accepted only if an auction is OPEN\n////////////////////////////////////////////////////////////////\n\ntype Bid struct {\n\tAuctionID string\n\tRecType   string // BID\n\tBidNo     string\n\tItemID    string\n\tBuyerID   string // ID Of Buyer - to be verified against the Item CurrentOwnerId\n\tBidPrice  string // BidPrice > Previous Bid\n\tBidTime   string // Time the bid was received\n}\n\n//////////////////////////////////////////////////////////////\n// Invoke Functions based on Function name\n// The function name gets resolved to one of the following calls\n// during an invoke\n//\n//////////////////////////////////////////////////////////////\nfunc InvokeFunction(fname string) func(stub shim.ChaincodeStubInterface, function string, args []string) pb.Response {\n\tInvokeFunc := map[string]func(stub shim.ChaincodeStubInterface, function string, args []string) pb.Response{\n\t\t\"iPostItem\":           PostItem,\n\t\t\"iPostUser\":           PostUser,\n\t\t\"iPostAuctionRequest\": PostAuctionRequest,\n\t\t\"iPostTransaction\":    PostTransaction,\n\t\t\"iPostBid\":            PostBid,\n\t\t\"iOpenAuctionForBids\": OpenAuctionForBids,\n\t\t\"iBuyItNow\":           BuyItNow,\n\t\t\"iTransferItem\":       TransferItem,\n\t\t\"iCloseAuction\":       CloseAuction,\n\t\t\"iCloseOpenAuctions\":  CloseOpenAuctions,\n\t}\n\treturn InvokeFunc[fname]\n}\n\n//////////////////////////////////////////////////////////////\n// Query Functions based on Function name\n//\n//////////////////////////////////////////////////////////////\nfunc QueryFunction(fname string) func(stub shim.ChaincodeStubInterface, function string, args []string) pb.Response {\n\tQueryFunc := map[string]func(stub shim.ChaincodeStubInterface, function string, args []string) pb.Response{\n\t\t\"qGetItem\":               GetItem,\n\t\t\"qGetUser\":               GetUser,\n\t\t\"qGetAuctionRequest\":     GetAuctionRequest,\n\t\t\"qGetTransaction\":        GetTransaction,\n\t\t\"qGetBid\":                GetBid,\n\t\t\"qGetLastBid\":            GetLastBid,\n\t\t\"qGetHighestBid\":         GetHighestBid,\n\t\t\"qGetNoOfBidsReceived\":   GetNoOfBidsReceived,\n\t\t\"qGetListOfBids\":         GetListOfBids,\n\t\t\"qGetItemLog\":            GetItemLog,\n\t\t\"qGetItemListByCat\":      GetItemListByCat,\n\t\t\"qGetUserListByCat\":      GetUserListByCat,\n\t\t\"qGetListOfInitAucs\":     GetListOfInitAucs,\n\t\t\"qGetListOfOpenAucs\":     GetListOfOpenAucs,\n\t\t\"qValidateItemOwnership\": ValidateItemOwnership,\n\t}\n\treturn QueryFunc[fname]\n}\n\n/////////////////////////////////////////////////////////////////////////////////////////////////////\n// A Map that holds ObjectNames and the number of Keys\n// This information is used to dynamically Create, Update\n// Replace , and Query the Ledger\n// In this model all attributes in a table are strings\n// The chain code does both validation\n// A dummy key like 2016 in some cases is used for a query to get all rows\n//\n//              \"User\":        1, Key: UserID\n//              \"Item\":        1, Key: ItemID\n//              \"UserCat\":     3, Key: \"2016\", UserType, UserID\n//              \"ItemCat\":     3, Key: \"2016\", ItemSubject, ItemID\n//              \"Auction\":     1, Key: AuctionID\n//              \"AucInit\":     2, Key: Year, AuctionID\n//              \"AucOpen\":     2, Key: Year, AuctionID\n//              \"Trans\":       2, Key: AuctionID, ItemID\n//              \"Bid\":         2, Key: AuctionID, BidNo\n//              \"ItemHistory\": 4, Key: ItemID, Status, AuctionHouseID(if applicable),date-time\n//\n// The additional key is the ObjectType (aka ObjectName or Object). The keys  would be\n// keys: {\"picname\", \"https://raw.githubusercontent.com/ITPeople-Blockchain/auction/v0.6/art/artchaincode/art1.png\"}\n/////////////////////////////////////////////////////////////////////////////////////////////////////\n\n//func GetPictureUrl(picname string) string {\n\tvar PictureMap = map[string]string {\n\t\t\"art1.png\":        \"https://raw.githubusercontent.com/ITPeople-Blockchain/auction/v0.6/art/artchaincode/art1.png\",\n\t\t\"art2.png\":        \"https://raw.githubusercontent.com/ITPeople-Blockchain/auction/v0.6/art/artchaincode/art2.png\",\n\t\t\"art3.png\":        \"https://raw.githubusercontent.com/ITPeople-Blockchain/auction/v0.6/art/artchaincode/art3.png\",\n\t\t\"art4.png\":        \"https://raw.githubusercontent.com/ITPeople-Blockchain/auction/v0.6/art/artchaincode/art4.png\",\n\t\t\"art5.png\":        \"https://raw.githubusercontent.com/ITPeople-Blockchain/auction/v0.6/art/artchaincode/art5.png\",\n\t\t\"art6.png\":        \"https://raw.githubusercontent.com/ITPeople-Blockchain/auction/v0.6/art/artchaincode/art6.png\",\n\t\t\"art7.png\":        \"https://raw.githubusercontent.com/ITPeople-Blockchain/auction/v0.6/art/artchaincode/art7.png\",\n\t\t\"item-001.jpg\":    \"https://raw.githubusercontent.com/ITPeople-Blockchain/auction/v0.6/art/artchaincode/item-001.jpg\",\n\t\t\"item-002.jpg\":    \"https://raw.githubusercontent.com/ITPeople-Blockchain/auction/v0.6/art/artchaincode/item-002.jpg\",\n\t\t\"item-003.jpg\":    \"https://raw.githubusercontent.com/ITPeople-Blockchain/auction/v0.6/art/artchaincode/item-003.jpg\",\n\t\t\"item-004.jpg\":    \"https://raw.githubusercontent.com/ITPeople-Blockchain/auction/v0.6/art/artchaincode/item-004.jpg\",\n\t\t\"item-005.jpg\":    \"https://raw.githubusercontent.com/ITPeople-Blockchain/auction/v0.6/art/artchaincode/item-005.jpg\",\n\t\t\"item-006.jpg\":    \"https://raw.githubusercontent.com/ITPeople-Blockchain/auction/v0.6/art/artchaincode/item-006.jpg\",\n\t\t\"item-007.jpg\":    \"https://raw.githubusercontent.com/ITPeople-Blockchain/auction/v0.6/art/artchaincode/item-007.jpg\",\n\t\t\"item-008.jpg\":    \"https://raw.githubusercontent.com/ITPeople-Blockchain/auction/v0.6/art/artchaincode/item-008.jpg\",\n\t\t\"people.gif\":      \"https://raw.githubusercontent.com/ITPeople-Blockchain/auction/v0.6/art/artchaincode/people.gif\",\n\t\t\"mad-fb.jpg\":      \"https://raw.githubusercontent.com/ITPeople-Blockchain/auction/v0.6/art/artchaincode/mad-fb.gif\",\n\t\t\"sample.png\":      \"https://raw.githubusercontent.com/ITPeople-Blockchain/auction/v0.6/art/artchaincode/sample.png\",\n\t}\n//\treturn PictureMap[picname]\n//}\n//var myLogger = logging.MustGetLogger(\"auction_trading\")\n\ntype SimpleChaincode struct {\n}\n\n\n////////////////////////////////////////////////////////////////////////////////\n// Chain Code Kick-off Main function\n////////////////////////////////////////////////////////////////////////////////\nfunc main() {\n\n\t// maximize CPU usage for maximum performance\n\truntime.GOMAXPROCS(runtime.NumCPU())\n\tfmt.Println(\"Starting Item Auction Application chaincode BlueMix ver 21 Dated 2016-07-02 09.45.00: \")\n\n\t//ccPath = fmt.Sprintf(\"%s/src/github.com/hyperledger/fabric/auction/art/artchaincode/\", gopath)\n\t// Start the shim -- running the fabric\n\terr := shim.Start(new(SimpleChaincode))\n\tif err != nil {\n\t\tfmt.Println(\"Error starting Item Fun Application chaincode: %s\", err)\n\t}\n\n}\n\nfunc downloadFile(filepath string, url string) (err error) {\n\n  // Create the file\n  out, err := os.Create(filepath)\n  if err != nil  {\n    return err\n  }\n  defer out.Close()\n\n  // Get the data\n  resp, err := http.Get(url)\n  if err != nil {\n    return err\n  }\n  defer resp.Body.Close()\n\n  // Writer the body to file\n  _, err = io.Copy(out, resp.Body)\n  if err != nil  {\n    return err\n  }\n\n  return nil\n}\n\n////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n// SimpleChaincode - Init Chaincode implementation - The following sequence of transactions can be used to test the Chaincode\n////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n\nfunc (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface) pb.Response {\n\n\t// TODO - Include all initialization to be complete before Invoke and Query\n\t// Uses aucTables to delete tables if they exist and re-create them\n\n\t//myLogger.Info(\"[Trade and Auction Application] Init\")\n\tfmt.Println(\"[Trade and Auction Application] Init\")\n\tvar err error\n        // TODO: could we rather save the hash of the picture on the BC ?\n\tfor k, v := range PictureMap { \n    \t\tfmt.Printf(\"\\n Downloading Image '%s' from URL:  %s\", k, v)\n\t        err = downloadFile(k, v)\n\t        if err != nil {\n\t        \tfmt.Println(err)\n\t\t\treturn shim.Error(\"Invoke: Invalid Function Name - function names begin with a q or i\")\n\t\t}\n\t}\n\tfmt.Println(\"\\nInit() Initialization Complete \")\n\treturn shim.Success(nil)\n}\n\n////////////////////////////////////////////////////////////////\n// SimpleChaincode - INVOKE Chaincode implementation\n// User Can Invoke\n// - Register a user using PostUser\n// - Register an item using PostItem\n// - The Owner of the item (User) can request that the item be put on auction using PostAuctionRequest\n// - The Auction House can request that the auction request be Opened for bids using OpenAuctionForBids\n// - One the auction is OPEN, registered buyers (Buyers) can send in bids vis PostBid\n// - No bid is accepted when the status of the auction request is INIT or CLOSED\n// - Either manually or by OpenAuctionRequest, the auction can be closed using CloseAuction\n// - The CloseAuction creates a transaction and invokes PostTransaction\n////////////////////////////////////////////////////////////////\n\nfunc (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response {\n\n\tfunction, args := stub.GetFunctionAndParameters()\n\tfmt.Println(\"==========================================================\")\n\tfmt.Println(\"BEGIN Function ====> \", function)\n\tif function[0:1] == \"i\" {\n\t\tfmt.Println(\"==========================================================\")\n\t\treturn t.invoke(stub, function, args)\n\t}\n\n\tif function[0:1] == \"q\" {\n\t\tfmt.Println(\"==========================================================\")\n\t\treturn t.query(stub, function, args)\n\t}\n\n\tfmt.Println(\"==========================================================\")\n\n\treturn shim.Error(\"Invoke: Invalid Function Name - function names begin with a q or i\")\n\n}\n\n////////////////////////////////////////////////////////////////\n// SimpleChaincode - INVOKE Chaincode implementation\n// User Can Invoke\n// - Register a user using PostUser\n// - Register an item using PostItem\n// - The Owner of the item (User) can request that the item be put on auction using PostAuctionRequest\n// - The Auction House can request that the auction request be Opened for bids using OpenAuctionForBids\n// - One the auction is OPEN, registered buyers (Buyers) can send in bids vis PostBid\n// - No bid is accepted when the status of the auction request is INIT or CLOSED\n// - Either manually or by OpenAuctionRequest, the auction can be closed using CloseAuction\n// - The CloseAuction creates a transaction and invokes PostTransaction\n////////////////////////////////////////////////////////////////\n\nfunc (t *SimpleChaincode) invoke(stub shim.ChaincodeStubInterface, function string, args []string) pb.Response {\n\n\t//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n\t// Check Type of Transaction and apply business rules\n\t// before adding record to the block chain\n\t// In this version, the assumption is that args[1] specifies recType for all defined structs\n\t// Newer structs - the recType can be positioned anywhere and ChkReqType will check for recType\n\t// example:\n\t// ./peer chaincode invoke -l golang -n mycc -c '{\"Function\": \"PostBid\", \"Args\":[\"1111\", \"BID\", \"1\", \"1000\", \"300\", \"1200\"]}'\n\t//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n\n\tif itpUtils.ChkRecType(args) == true {\n\n\t\tInvokeRequest := InvokeFunction(function)\n\t\tif InvokeRequest != nil {\n\t\t\tresponse := InvokeRequest(stub, function, args)\n\t\t\treturn (response)\n\t\t}\n\t} else {\n\t\tfmt.Println(\"Invoke() Invalid recType : \", args, \"\\n\")\n\t\terror_str := \"Invoke() : Invalid recType : \" + args[0]\n\t\treturn shim.Error(error_str)\n\t}\n\n\treturn shim.Success(nil)\n}\n\n//////////////////////////////////////////////////////////////////////////////////////////\n// SimpleChaincode - query Chaincode implementation\n// Client Can Query\n// Sample Data\n// ./peer chaincode query -l golang -n mycc -c '{\"Function\": \"GetUser\", \"Args\": [\"4000\"]}'\n// ./peer chaincode query -l golang -n mycc -c '{\"Function\": \"GetItem\", \"Args\": [\"2000\"]}'\n//////////////////////////////////////////////////////////////////////////////////////////\n\nfunc (t *SimpleChaincode) query(stub shim.ChaincodeStubInterface, function string, args []string) pb.Response {\n\n\t// var buff []byte\n\tvar response pb.Response\n\tfmt.Println(\"Query() : ID Extracted and Type = \", args[0])\n\tfmt.Println(\"Query() : Args supplied : \", args)\n\n\tif len(args) < 1 {\n\t\tfmt.Println(\"Query() : Include at least 1 arguments Key \")\n\t\treturn shim.Error(\"Query() : Expecting Transation type and Key value for query\")\n\t}\n\n\tQueryRequest := QueryFunction(function)\n\tif QueryRequest != nil {\n\t\tresponse = QueryRequest(stub, function, args)\n\t} else {\n\t\tfmt.Println(\"Query() Invalid function call : \", function)\n\t\tresponse_str := \"Query() : Invalid function call : \" + function\n\t\treturn shim.Error(response_str)\n\t}\n\n\tif response.Status != shim.OK {\n\t\tfmt.Println(\"Query() Object not found : \", args[0])\n\t\tresponse_str := \"Query() : Object not found : \" + args[0]\n\t\treturn shim.Error(response_str)\n\t}\n\treturn response\n}\n\n//////////////////////////////////////////////////////////////////////////////////////////\n// Retrieve User Information\n// example:\n// ./peer chaincode query -l golang -n mycc -c '{\"Function\": \"GetUser\", \"Args\": [\"100\"]}'\n//\n//////////////////////////////////////////////////////////////////////////////////////////\nfunc GetUser(stub shim.ChaincodeStubInterface, function string, args []string) pb.Response {\n\n\tvar err error\n\n\t// Get the Object and Display it\n\tAvalbytes, err := itpUtils.QueryObject(stub, \"User\", args)\n\tif err != nil {\n\t\tfmt.Println(\"GetUser() : Failed to Query Object \")\n\t\tjsonResp := \"{\\\"Error\\\":\\\"Failed to get  Object Data for \" + args[0] + \"\\\"}\"\n\t\treturn shim.Error(jsonResp)\n\t}\n\n\tif Avalbytes == nil {\n\t\tfmt.Println(\"GetUser() : Incomplete Query Object \")\n\t\tjsonResp := \"{\\\"Error\\\":\\\"Incomplete information about the key for \" + args[0] + \"\\\"}\"\n\t\treturn shim.Error(jsonResp)\n\t}\n\n\tfmt.Println(\"GetUser() : Response : Successfull -\")\n\treturn shim.Success(Avalbytes)\n}\n\n/////////////////////////////////////////////////////////////////////////////////////////\n// Query callback representing the query of a chaincode\n// Retrieve a Item by Item ID\n// itpUtils.QueryObjectWithProcessingFunction takes a post processing function as argument\n// peer chaincode query -l golang -n mycc -c '{\"Args\": [\"qGetItem\", \"1000\"]}\n//\n/////////////////////////////////////////////////////////////////////////////////////////\nfunc GetItem(stub shim.ChaincodeStubInterface, function string, args []string) pb.Response {\n\n\tvar err error\n\n\t// Get the Objects and Display it\n\tAvalbytes, err := itpUtils.QueryObjectWithProcessingFunction(stub, \"Item\", args, ProcessQueryResult)\n\tif err != nil {\n\t\tfmt.Println(\"GetItem() : Failed to Query Object \")\n\t\tjsonResp := \"{\\\"Error\\\":\\\"Failed to get  Object Data for \" + args[0] + \"\\\"}\"\n\t\treturn shim.Error(jsonResp)\n\t}\n\n\tif Avalbytes == nil {\n\t\tfmt.Println(\"GetItem() : Incomplete Query Object \")\n\t\tjsonResp := \"{\\\"Error\\\":\\\"Incomplete information about the key for \" + args[0] + \"\\\"}\"\n\t\treturn shim.Error(jsonResp)\n\t}\n\n\tfmt.Println(\"GetItem() : Response : Successfull \")\n\treturn shim.Success(Avalbytes)\n}\n\n/////////////////////////////////////////////////////////////////////////////////////////\n// Validates The Ownership of an Asset using ItemID, OwnerID, and HashKey\n//\n// ./peer chaincode query -l golang -n mycc -c '{\"Function\": \"ValidateItemOwnership\", \"Args\": [\"1000\", \"100\", \"tGEBaZuKUBmwTjzNEyd+nr/fPUASuVJAZ1u7gha5fJg=\"]}'\n//\n/////////////////////////////////////////////////////////////////////////////////////////\nfunc ValidateItemOwnership(stub shim.ChaincodeStubInterface, function string, args []string) pb.Response {\n\n\tvar err error\n\n\tif len(args) < 3 {\n\t\tfmt.Println(\"ValidateItemOwnership() : Requires 3 arguments Item#, Owner# and Key \")\n\t\treturn shim.Error(\"ValidateItemOwnership() : Requires 3 arguments Item#, Owner# and Key\")\n\t}\n\n\t// Get the Object Information\n\tAvalbytes, err := itpUtils.QueryObject(stub, \"Item\", []string{args[0]})\n\tif err != nil {\n\t\tfmt.Println(\"ValidateItemOwnership() : Failed to Query Object \")\n\t\tjsonResp := \"{\\\"Error\\\":\\\"Failed to get  Object Data for \" + args[0] + \"\\\"}\"\n\t\treturn shim.Error(jsonResp)\n\t}\n\n\tif Avalbytes == nil {\n\t\tfmt.Println(\"ValidateItemOwnership() : Incomplete Query Object \")\n\t\tjsonResp := \"{\\\"Error\\\":\\\"Incomplete information about the key for \" + args[0] + \"\\\"}\"\n\t\treturn shim.Error(jsonResp)\n\t}\n\n\tmyItem, err := JSONtoAR(Avalbytes)\n\tif err != nil {\n\t\tfmt.Println(\"ValidateItemOwnership() : Failed to Query Object \")\n\t\tjsonResp := \"{\\\"Error\\\":\\\"Failed to get  Object Data for \" + args[0] + \"\\\"}\"\n\t\treturn shim.Error(jsonResp)\n\t}\n\n\tmyKey := GetKeyValue(Avalbytes, \"AES_Key\")\n\tfmt.Println(\"Key String := \", myKey)\n\n\tif myKey != args[2] {\n\t\tfmt.Println(\"ValidateItemOwnership() : Key does not match supplied key \", args[2], \" - \", myKey)\n\t\tjsonResp := \"{\\\"Error\\\":\\\"ValidateItemOwnership() : Key does not match asset owner supplied key  \" + args[0] + \"\\\"}\"\n\t\treturn shim.Error(jsonResp)\n\t}\n\n\tif myItem.CurrentOwnerID != args[1] {\n\t\tfmt.Println(\"ValidateItemOwnership() : ValidateItemOwnership() : Owner-Id does not match supplied ID \", args[1])\n\t\tjsonResp := \"{\\\"Error\\\":\\\"ValidateItemOwnership() : Owner-Id does not match supplied ID \" + args[0] + \"\\\"}\"\n\t\treturn shim.Error(jsonResp)\n\t}\n\n\tfmt.Print(\"ValidateItemOwnership() : Response : Successfull - \\n\")\n\treturn shim.Success(Avalbytes)\n}\n\n/////////////////////////////////////////////////////////////////////////////////////////////////////\n// Retrieve Auction Information\n// This query runs against the AuctionTable\n// ./peer chaincode query -l golang -n mycc -c '{\"Function\": \"GetAuctionRequest\", \"Args\": [\"1111\"]}'\n// There are two other tables just for query purposes - AucInitTable, AucOpenTable\n//\n/////////////////////////////////////////////////////////////////////////////////////////////////////\nfunc GetAuctionRequest(stub shim.ChaincodeStubInterface, function string, args []string) pb.Response {\n\n\tvar err error\n\n\t// Get the Objects and Display it\n\tAvalbytes, err := itpUtils.QueryObject(stub, \"Auction\", args)\n\tif err != nil {\n\t\tfmt.Println(\"GetAuctionRequest() : Failed to Query Object \")\n\t\tjsonResp := \"{\\\"Error\\\":\\\"Failed to get  Object Data for \" + args[0] + \"\\\"}\"\n\t\treturn shim.Error(jsonResp)\n\t}\n\n\tif Avalbytes == nil {\n\t\tfmt.Println(\"GetAuctionRequest() : Incomplete Query Object \")\n\t\tjsonResp := \"{\\\"Error\\\":\\\"Incomplete information about the key for \" + args[0] + \"\\\"}\"\n\t\treturn shim.Error(jsonResp)\n\t}\n\n\tfmt.Println(\"GetAuctionRequest() : Response : Successfull - \\n\")\n\treturn shim.Success(Avalbytes)\n}\n\n///////////////////////////////////////////////////////////////////////////////////////////////////\n// Retrieve a Bid based on two keys - AucID, BidNo\n// A Bid has two Keys - The Auction Request Number and Bid Number\n// ./peer chaincode query -l golang -n mycc -c '{\"Function\": \"GetLastBid\", \"Args\": [\"1111\", \"1\"]}'\n//\n///////////////////////////////////////////////////////////////////////////////////////////////////\nfunc GetBid(stub shim.ChaincodeStubInterface, function string, args []string) pb.Response {\n\n\tvar err error\n\n\t// Check there are 2 Arguments provided as per the the struct - two are computed\n\t// See example\n\tif len(args) < 2 {\n\t\tfmt.Println(\"GetBid(): Incorrect number of arguments. Expecting 2 \")\n\t\tfmt.Println(\"GetBid(): ./peer chaincode query -l golang -n mycc -c '{\\\"Function\\\": \\\"GetBid\\\", \\\"Args\\\": [\\\"1111\\\",\\\"6\\\"]}'\")\n\t\treturn shim.Error(\"GetBid(): Incorrect number of arguments. Expecting 2 \")\n\t}\n\n\t// Get the Objects and Display it\n\tAvalbytes, err := itpUtils.QueryObject(stub, \"Bid\", args)\n\tif err != nil {\n\t\tfmt.Println(\"GetBid() : Failed to Query Object \")\n\t\tjsonResp := \"{\\\"Error\\\":\\\"Failed to get  Object Data for \" + args[0] + \"\\\"}\"\n\t\treturn shim.Error(jsonResp)\n\t}\n\n\tif Avalbytes == nil {\n\t\tfmt.Println(\"GetBid() : Incomplete Query Object \")\n\t\tjsonResp := \"{\\\"Error\\\":\\\"Incomplete information about the key for \" + args[0] + \"\\\"}\"\n\t\treturn shim.Error(jsonResp)\n\t}\n\n\tfmt.Println(\"GetBid() : Response : Successfull -\")\n\treturn shim.Success(Avalbytes)\n}\n\n///////////////////////////////////////////////////////////////////////////////////////////////////\n// Retrieve Auction Closeout Information. When an Auction closes\n// The highest bid is retrieved and converted to a Transaction\n//  ./peer chaincode query -l golang -n mycc -c '{\"Function\": \"GetTransaction\", \"Args\": [\"1111\"]}'\n//\n///////////////////////////////////////////////////////////////////////////////////////////////////\nfunc GetTransaction(stub shim.ChaincodeStubInterface, function string, args []string) pb.Response {\n\n\t//var err error\n\n\t// Get the Objects and Display it\n\tAvalbytes, err := itpUtils.QueryObject(stub, \"Trans\", args)\n\tif Avalbytes == nil {\n\t\tfmt.Println(\"GetTransaction() : Incomplete Query Object \")\n\t\tjsonResp := \"{\\\"Error\\\":\\\"Incomplete information about the key for \" + args[0] + \"\\\"}\"\n\t\treturn shim.Error(jsonResp)\n\t}\n\n\tif err != nil {\n\t\tfmt.Println(\"GetTransaction() : Failed to Query Object \")\n\t\tjsonResp := \"{\\\"Error\\\":\\\"Failed to get  Object Data for \" + args[0] + \"\\\"}\"\n\t\treturn shim.Error(jsonResp)\n\t}\n\n\tfmt.Println(\"GetTransaction() : Response : Successfull\")\n\treturn shim.Success(Avalbytes)\n}\n\n///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n// Create a User Object. The first step is to have users\n// registered\n// There are different types of users - Traders (TRD), Auction Houses (AH)\n// Shippers (SHP), Insurance Companies (INS), Banks (BNK)\n// While this version of the chain code does not enforce strict validation\n// the business process recomends validating each persona for the service\n// they provide or their participation on the auction blockchain, future enhancements will do that\n// ./peer chaincode invoke -l golang -n mycc -c '{\"Function\": \"PostUser\", \"Args\":[\"100\", \"USER\", \"Ashley Hart\", \"TRD\",  \"Morrisville Parkway, #216, Morrisville, NC 27560\", \"9198063535\", \"ashley@itpeople.com\", \"SUNTRUST\", \"00017102345\", \"0234678\"]}'\n///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n\nfunc PostUser(stub shim.ChaincodeStubInterface, function string, args []string) pb.Response {\n\n\trecord, err := CreateUserObject(args[0:]) //\n\tif err != nil {\n\t\treturn shim.Error(err.Error())\n\t}\n\tbuff, err := UsertoJSON(record) //\n\n\tif err != nil {\n\t\terror_str := \"PostuserObject() : Failed Cannot create object buffer for write : \" + args[1]\n\t\tfmt.Println(error_str)\n\t\treturn shim.Error(error_str)\n\t} else {\n\t\t// Update the ledger with the Buffer Data\n\t\t// err = stub.PutState(args[0], buff)\n\t\tkeys := []string{args[0]}\n\t\terr = itpUtils.UpdateObject(stub, \"User\", keys, buff)\n\t\tif err != nil {\n\t\t\tfmt.Println(\"PostUser() : write error while inserting record\")\n\t\t\treturn shim.Error(\"PostUser() : write error while inserting record : Error - \" + err.Error())\n\t\t}\n\n\t\t// Post Entry into UserCat- i.e. User Category Table\n\t\tkeys = []string{\"2016\", args[3], args[0]}\n\t\terr = itpUtils.UpdateObject(stub, \"UserCat\", keys, buff)\n\t\tif err != nil {\n\t\t\terror_str := \"PostUser() : write error while inserting recordinto UserCat\"\n\t\t\tfmt.Println(error_str)\n\t\t\treturn shim.Error(error_str)\n\t\t}\n\t}\n\n\treturn shim.Success(buff)\n}\n\nfunc CreateUserObject(args []string) (UserObject, error) {\n\n\tvar err error\n\tvar aUser UserObject\n\n\t// Check there are 11 Arguments\n\tif len(args) != 11 {\n\t\tfmt.Println(\"CreateUserObject(): Incorrect number of arguments. Expecting 11 \")\n\t\treturn aUser, errors.New(\"CreateUserObject() : Incorrect number of arguments. Expecting 11 \")\n\t}\n\n\t// Validate UserID is an integer\n\n\t_, err = strconv.Atoi(args[0])\n\tif err != nil {\n\t\treturn aUser, errors.New(\"CreateUserObject() : User ID should be an integer\")\n\t}\n\n\taUser = UserObject{args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10]}\n\tfmt.Println(\"CreateUserObject() : User Object : \", aUser)\n\n\treturn aUser, nil\n}\n\n/////////////////////////////////////////////////////////////////////////////////////////////////////////////\n// Create a master Object of the Item\n// Since the Owner Changes hands, a record has to be written for each\n// Transaction with the updated Encryption Key of the new owner\n// Example\n//./peer chaincode invoke -l golang -n mycc -c '{\"Function\": \"PostItem\", \"Args\":[\"1000\", \"ARTINV\", \"Shadows by Asppen\", \"Asppen Messer\", \"20140202\", \"Original\", \"Landscape\" , \"Canvas\", \"15 x 15 in\", \"sample_7.png\",\"$600\", \"100\", \"2016-02-02 03:000:00\"]}'\n/////////////////////////////////////////////////////////////////////////////////////////////////////////////\n\nfunc PostItem(stub shim.ChaincodeStubInterface, function string, args []string) pb.Response {\n\n\titemObject, err := CreateItemObject(args[0:])\n\tif err != nil {\n\t\tfmt.Println(\"PostItem(): Cannot create item object \\n\")\n\t\treturn shim.Error(\"PostItem(): Cannot create item object\")\n\t}\n\n\t// Check if the Owner ID specified is registered and valid\n\tresponse := ValidateMember(stub, itemObject.CurrentOwnerID)\n\townerInfo := response.Payload\n\tfmt.Println(\"Owner information  \", ownerInfo, itemObject.CurrentOwnerID)\n\tif response.Status != shim.OK {\n\t\terror_str := \"PostItem() : Failed Owner information not found for \" + itemObject.CurrentOwnerID\n\t\tfmt.Println(error_str)\n\t\treturn shim.Error(error_str)\n\t}\n\n\t// Convert Item Object to JSON\n\tbuff, err := ARtoJSON(itemObject) //\n\tif err != nil {\n\t\terror_str := \"PostItem() : Failed Cannot create object buffer for write : \" + args[1]\n\t\tfmt.Println(error_str)\n\t\treturn shim.Error(error_str)\n\t} else {\n\t\t// Update the ledger with the Buffer Data\n\t\t// err = stub.PutState(args[0], buff)\n\t\tkeys := []string{args[0]}\n\t\terr = itpUtils.UpdateObject(stub, \"Item\", keys, buff)\n\t\tif err != nil {\n\t\t\tfmt.Println(\"PostItem() : write error while inserting record\\n\")\n\t\t\treturn shim.Error(\"PostItem() : write error while inserting record : \" + err.Error())\n\t\t}\n\n\t\t// Put an entry into the Item History Table\n\t\tresponse := PostItemLog(stub, itemObject, \"INITIAL\", \"DEFAULT\", args[12])\n\t\tif response.Status != shim.OK {\n\t\t\tfmt.Println(\"PostItemLog() : write error while inserting record\\n\")\n\t\t\treturn shim.Error(\"PostItemLog() : write error while inserting record : Error : \" + err.Error())\n\t\t}\n\n\t\t// Post Entry into ItemCatTable - i.e. Item Category Table\n\t\t// The first key 2016 is a dummy (band aid) key to extract all values\n\t\tkeys = []string{\"2016\", args[6], args[0]}\n\t\terr = itpUtils.UpdateObject(stub, \"ItemCat\", keys, buff)\n\t\tif err != nil {\n\t\t\tfmt.Println(\"PostItem() : Write error while inserting record into ItemCat \\n\")\n\t\t\treturn shim.Error(\"PostItem() : Write error while inserting record into ItemCat :   Error : \" + err.Error())\n\t\t}\n\t}\n\n\tsecret_key, _ := json.Marshal(itemObject.AES_Key)\n\tfmt.Println(string(secret_key))\n\treturn shim.Success(secret_key)\n}\n\nfunc CreateItemObject(args []string) (ItemObject, error) {\n\n\tvar err error\n\tvar myItem ItemObject\n\n\t// Check there are 13 Arguments provided as per the the struct - two are computed\n\tif len(args) != 13 {\n\t\tfmt.Println(\"CreateItemObject(): Incorrect number of arguments. Expecting 13 \")\n\t\treturn myItem, errors.New(\"CreateItemObject(): Incorrect number of arguments. Expecting 13 \")\n\t}\n\n\t// Validate ItemID is an integer\n\n\t_, err = strconv.Atoi(args[0])\n\tif err != nil {\n\t\tfmt.Println(\"CreateItemObject(): ART ID should be an integer create failed! \")\n\t\treturn myItem, errors.New(\"CreateItemObject(): ART ID should be an integer create failed!\")\n\t}\n\n\t// Validate Picture File exists based on the name provided\n\t// Looks for file in current directory of application and must be fixed for other locations\n\n\t// Validate Picture File exists based on the name provided\n\t// Looks for file in current directory of application and must be fixed for other locations\n\timagePath := args[9]\n\tif _, err := os.Stat(imagePath); err == nil {\n\t\tfmt.Println(imagePath, \"  exists!\")\n\t} else {\n\t\tfmt.Println(\"CreateItemObject(): Cannot find or load Picture File = %s :  %s\\n\", imagePath, err)\n\t\treturn myItem, errors.New(\"CreateItemObject(): ART Picture File not found \" + imagePath)\n\t}\n\n\t// Get the Item Image and convert it to a byte array\n\timagebytes, fileType := itpUtils.ImageToByteArray(imagePath)\n\n\t// Generate a new key and encrypt the image\n\n\tAES_key, _ := itpUtils.GenAESKey()\n\tAES_enc := itpUtils.Encrypt(AES_key, imagebytes)\n\n\t// Append the AES Key, The Encrypted Image Byte Array and the file type\n\tmyItem = ItemObject{args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], AES_enc, AES_key, fileType, args[10], args[11], args[12]}\n\n\tfmt.Println(\"CreateItemObject(): Item Object created: \", myItem.ItemID, myItem.AES_Key)\n\n\t// Code to Validate the Item Object)\n\t// If User presents Crypto Key then key is used to validate the picture that is stored as part of the title\n\t// TODO\n\n\treturn myItem, nil\n}\n\n///////////////////////////////////////////////////////////////////////////////////\n// Since the Owner Changes hands, a record has to be written for each\n// Transaction with the updated Encryption Key of the new owner\n// This function is internally invoked by PostTransaction and is not a Public API\n///////////////////////////////////////////////////////////////////////////////////\n\nfunc UpdateItemObject(stub shim.ChaincodeStubInterface, ar []byte, hammerPrice string, buyer string) pb.Response {\n\n\tvar err error\n\tmyItem, err := JSONtoAR(ar)\n\tif err != nil {\n\t\tfmt.Println(\"UpdateItemObject() : Failed to create Art Record Object from JSON \")\n\t\treturn shim.Error(\"UpdateItemObject() : Failed to create Art Record Object from JSON : Error : \" + err.Error())\n\t}\n\n\t// Insert logic to  re-encrypt image by first fetching the current Key\n\tCurrentAES_Key := myItem.AES_Key\n\t// Decrypt Image and Save Image in a file\n\timage := itpUtils.Decrypt(CurrentAES_Key, myItem.ItemImage)\n\n\t// Get a New Key & Encrypt Image with New Key\n\tmyItem.AES_Key, _ = itpUtils.GenAESKey()\n\tmyItem.ItemImage = itpUtils.Encrypt(myItem.AES_Key, image)\n\n\t// Update the owner to the Buyer and update price to auction hammer price\n\tmyItem.ItemBasePrice = hammerPrice\n\tmyItem.CurrentOwnerID = buyer\n\n\tar, err = ARtoJSON(myItem)\n\t// keys := []string{myItem.ItemID, myItem.CurrentOwnerID}    // Was the original in v0.6\n\tkeys := []string{myItem.ItemID}\n\terr = itpUtils.ReplaceObject(stub, \"Item\", keys, ar)\n\tif err != nil {\n\t\tfmt.Println(\"UpdateItemObject() : Failed ReplaceObject in ItemTable into Blockchain \")\n\t\treturn shim.Error(\"UpdateItemObject() : Failed ReplaceObject in ItemTable into Blockchain : Error : \" + err.Error())\n\t}\n\tfmt.Println(\"UpdateItemObject() : ReplaceObject in Item successful \")\n\n\t// Update entry in Item Category Table as it holds the Item object as wekk\n\tkeys = []string{\"2016\", myItem.ItemSubject, myItem.ItemID}\n\terr = itpUtils.ReplaceObject(stub, \"ItemCat\", keys, ar)\n\tif err != nil {\n\t\tfmt.Println(\"UpdateItemObject() : Failed ReplaceObject in ItemCategory into Blockchain \")\n\t\treturn shim.Error(\"UpdateItemObject() : Failed ReplaceObject in ItemCategory into Blockchain : Error : \" + err.Error())\n\t}\n\n\tfmt.Println(\"UpdateItemObject() : ReplaceObject in ItemCategory successful \")\n\treturn shim.Success(myItem.AES_Key)\n}\n\n///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n// Obtain Asset Details and Validate Item\n// Transfer Item to new owner - no change in price  - In the example XFER is the recType\n// ./peer chaincode invoke -l golang -n mycc -c '{\"Function\": \"TransferItem\", \"Args\": [\"1000\", \"100\", \"tGEBaZuKUBmwTjzNEyd+nr/fPUASuVJAZ1u7gha5fJg=\", \"300\", \"XFER\"]}'\n///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\nfunc TransferItem(stub shim.ChaincodeStubInterface, function string, args []string) pb.Response {\n\n\tvar err error\n\n\tif len(args) < 6 {\n\t\tfmt.Println(\"TransferItem() : Requires 6 arguments Item#, Owner#, Key#, newOwnerID#, XFER \\n\")\n\t\treturn shim.Error(\"TransferItem() : Requires 6 arguments Item#, Owner#, Key#, newOwnerID#, XFER\")\n\t}\n\n\t// Let us make sure that the Item is not on Auction\n\terr = VerifyIfItemIsOnAuction(stub, args[0])\n\tif err != nil {\n\t\terror_str := \"TransferItem() : Failed Item is either initiated or opened for Auction \" + args[0]\n\t\tfmt.Println(error_str)\n\t\treturn shim.Error(error_str + \": Error : \" + err.Error())\n\t}\n\n\t// Validate New Owner's ID\n\tresponse := ValidateMember(stub, args[3])\n\tif response.Status != shim.OK {\n\t\terror_str := \"TransferItem() : Failed transferee not Registered in Blockchain \" + args[3]\n\t\tfmt.Println(error_str)\n\t\treturn shim.Error(error_str + \": Error : \" + response.Message)\n\t}\n\n\t// Validate Item or Asset Ownership\n\tresponse = ValidateItemOwnership(stub, \"ValidateItemOwnership\", args[:3])\n\tif response.Status != shim.OK {\n\t\terror_str := \"TransferItem() : ValidateItemOwnership() : Failed to authenticate item or asset ownership\"\n\t\tfmt.Println(error_str)\n\t\treturn shim.Error(error_str + \": Error : \" + response.Message)\n\t}\n\n\tar := response.Payload\n\tmyItem, err := JSONtoAR(ar)\n\tif err != nil {\n\t\terror_str := \"TransferItem() : Failed to create item Object from JSON \"\n\t\tfmt.Println(error_str)\n\t\treturn shim.Error(error_str + \": Error : \" + err.Error())\n\t}\n\n\t// Insert logic to  re-encrypt image by first fetching the current Key\n\tCurrentAES_Key := myItem.AES_Key\n\t// Decrypt Image and Save Image in a file\n\timage := itpUtils.Decrypt(CurrentAES_Key, myItem.ItemImage)\n\n\t// Get a New Key & Encrypt Image with New Key\n\tmyItem.AES_Key, _ = itpUtils.GenAESKey()\n\tmyItem.ItemImage = itpUtils.Encrypt(myItem.AES_Key, image)\n\n\t// Update the owner to the new owner transfered to\n\tmyItem.CurrentOwnerID = args[3]\n\n\tar, err = ARtoJSON(myItem)\n\tkeys := []string{myItem.ItemID}\n\terr = itpUtils.ReplaceObject(stub, \"Item\", keys, ar)\n\tif err != nil {\n\t\tfmt.Println(\"TransferAsset() : Failed ReplaceObject in ItemTable into Blockchain \")\n\t\treturn shim.Error(err.Error())\n\t}\n\tfmt.Println(\"TransferAsset() : ReplaceObject in Item successful \")\n\n\t// Update entry in Item Category Table as it holds the Item object as well\n\tkeys = []string{\"2016\", myItem.ItemSubject, myItem.ItemID}\n\terr = itpUtils.ReplaceObject(stub, \"ItemCat\", keys, ar)\n\tif err != nil {\n\t\tfmt.Println(\"TransferAsset() : Failed ReplaceObject in ItemCategoryTable into Blockchain \")\n\t\treturn shim.Error(err.Error())\n\t}\n\n\tresponse = PostItemLog(stub, myItem, \"Transfer\", args[1], args[5])\n\tif response.Status != shim.OK {\n\t\tfmt.Println(\"TransferItem() : PostItemLog() write error while inserting record\\n\")\n\t\treturn shim.Error(err.Error())\n\t}\n\n\tfmt.Println(\"TransferAsset() : ReplaceObject in ItemCategory successful \")\n\treturn shim.Success(myItem.AES_Key)\n}\n\n////////////////////////////////////////////////////////////////////////////////////\n// Validate Item Status - Is it currently on Auction, if so Reject Transfer Request\n// This can be written better - will do so if things work\n// The function return the Auction ID and the Status = OPEN or INIT\n////////////////////////////////////////////////////////////////////////////////////\n\nfunc VerifyIfItemIsOnAuction(stub shim.ChaincodeStubInterface, itemID string) error {\n\n\tresponse := GetListOfOpenAucs(stub, \"AucOpen\", []string{\"2016\"})\n\tif response.Status != shim.OK {\n\t\treturn fmt.Errorf(\"VerifyIfItemIsOnAuction() operation failed. Error retrieving values from AucOpen: %s\", response.Message)\n\t}\n\n\trows := response.Payload\n\ttlist := make([]AuctionRequest, len(rows))\n\terr := json.Unmarshal([]byte(rows), &tlist)\n\tif err != nil {\n\t\tfmt.Println(\"VerifyIfItemIsOnAuction: Unmarshal failed : \", err)\n\t\treturn fmt.Errorf(\"VerifyIfItemIsOnAuction: operation failed. Error un-marshaling JSON: %s\", err)\n\t}\n\n\tfor i := 0; i < len(tlist); i++ {\n\t\tar := tlist[i]\n\n\t\t// Compare Auction IDs\n\t\tif ar.ItemID == itemID {\n\t\t\tfmt.Println(\"VerifyIfItemIsOnAuction() Failed : Ummarshall error\")\n\t\t\treturn fmt.Errorf(\"VerifyIfItemIsOnAuction() operation failed. %s\", itemID)\n\t\t}\n\t}\n\n\t// Now Check if an Auction Has been inititiated\n\t// If so , it has to be removed from Auction for a Transfer\n\n\tresponse = GetListOfInitAucs(stub, \"AucInit\", []string{\"2016\"})\n\tif response.Status != shim.OK {\n\t\treturn fmt.Errorf(\"VerifyIfItemIsOnAuction() operation failed. Error retrieving values from AucInit: %s\", err)\n\t}\n\n\trows = response.Payload\n\ttlist = make([]AuctionRequest, len(rows))\n\terr = json.Unmarshal([]byte(rows), &tlist)\n\tif err != nil {\n\t\tfmt.Println(\"VerifyIfItemIsOnAuction() Unmarshal failed : \", err)\n\t\treturn fmt.Errorf(\"VerifyIfItemIsOnAuction: operation failed. Error un-marshaling JSON: %s\", err)\n\t}\n\n\tfor i := 0; i < len(tlist); i++ {\n\t\tar := tlist[i]\n\t\tif err != nil {\n\t\t\tfmt.Println(\"VerifyIfItemIsOnAuction() Failed : Ummarshall error\")\n\t\t\treturn fmt.Errorf(\"VerifyIfItemIsOnAuction() operation failed. %s\", err)\n\t\t}\n\n\t\t// Compare Auction IDs\n\t\tif ar.ItemID == itemID {\n\t\t\treturn fmt.Errorf(\"VerifyIfItemIsOnAuction() operation failed.\")\n\t\t}\n\t}\n\n\treturn nil\n}\n\n//////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n// POSTS A LOG ENTRY Every Time the Item is transacted\n// Valid Status for ItemLog =  OnAuc, OnSale, NA, INITIAL\n// Valid AuctionedBy: This value is set to \"DEFAULT\" but when it is put on auction Auction House ID is assigned\n// PostItemLog IS NOT A PUBLIC API and is invoked every time some event happens in the Item's life\n// The currentDateTime must be provided by Client\n//////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n\nfunc PostItemLog(stub shim.ChaincodeStubInterface, item ItemObject, status string, ah string, currentDateTime string) pb.Response {\n\n\tiLog := ItemToItemLog(item, currentDateTime)\n\tiLog.Status = status\n\tiLog.AuctionedBy = ah\n\n\tbuff, err := ItemLogtoJSON(iLog)\n\tif err != nil {\n\t\tfmt.Println(\"PostItemLog() : Failed Cannot create object buffer for write : \", item.ItemID)\n\t\treturn shim.Error(\"PostItemLog(): Failed Cannot create object buffer for write : \" + item.ItemID)\n\t} else {\n\t\t// Update the ledger with the Buffer Data\n\t\tkeys := []string{iLog.ItemID, iLog.Status, iLog.AuctionedBy, currentDateTime}\n\t\terr = itpUtils.UpdateObject(stub, \"ItemHistory\", keys, buff)\n\t\tif err != nil {\n\t\t\tfmt.Println(\"PostItemLog() : write error while inserting record\\n\")\n\t\t\treturn shim.Error(err.Error())\n\t\t}\n\t}\n\treturn shim.Success(buff)\n}\n\n//////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n// Create an Auction Request\n// The owner of an Item, when ready to put the item on an auction\n// will create an auction request  and specify a  auction house.\n//\n// ./peer chaincode invoke -l golang -n mycc -c '{\"Function\": \"PostAuctionRequest\", \"Args\":[\"1111\", \"AUCREQ\", \"1700\", \"200\", \"400\", \"04012016\", \"1200\", \"INIT\", \"2016-05-20 11:00:00.3 +0000 UTC\",\"2016-05-23 11:00:00.3 +0000 UTC\", \"2016-05-23 11:00:00.3 +0000 UTC\"]}'\n//\n// The start and end time of the auction are actually assigned when the auction is opened  by OpenAuctionForBids()\n///////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n\nfunc PostAuctionRequest(stub shim.ChaincodeStubInterface, function string, args []string) pb.Response {\n\n\tar, err := CreateAuctionRequest(args[0:])\n\tif err != nil {\n\t\treturn shim.Error(err.Error())\n\t}\n\n\t// Let us make sure that the Item is not on Auction\n\terr = VerifyIfItemIsOnAuction(stub, ar.ItemID)\n\tif err != nil {\n\t\tfmt.Println(\"PostAuctionRequest() : Failed Item is either initiated or opened for Auction \", args[0])\n\t\treturn shim.Error(err.Error())\n\t}\n\n\t// Validate Auction House to check it is a registered User\n\tresponse := ValidateMember(stub, ar.AuctionHouseID)\n\tif response.Status != shim.OK {\n\t\tfmt.Println(\"PostAuctionRequest() : Failed Auction House not Registered in Blockchain \", ar.AuctionHouseID)\n\t\treturn shim.Error(err.Error())\n\t}\n\n\taucHouse := response.Payload\n\tfmt.Println(\"Auction House information  \", aucHouse, \" ID: \", ar.AuctionHouseID)\n\n\t// Validate Item record\n\tresponse = ValidateItemSubmission(stub, ar.ItemID)\n\tif response.Status != shim.OK {\n\t\tfmt.Println(\"PostAuctionRequest() : Failed Could not Validate Item Object in Blockchain \", ar.ItemID)\n\t\treturn shim.Error(err.Error())\n\t}\n\n\titemObject := response.Payload\n\n\t// Convert AuctionRequest to JSON\n\tbuff, err := AucReqtoJSON(ar) // Converting the auction request struct to []byte array\n\tif err != nil {\n\t\tfmt.Println(\"PostAuctionRequest() : Failed Cannot create object buffer for write : \", args[1])\n\t\treturn shim.Error(\"PostAuctionRequest(): Failed Cannot create object buffer for write : \" + args[1])\n\t} else {\n\t\t// Update the ledger with the Buffer Data\n\t\t//err = stub.PutState(args[0], buff)\n\t\tkeys := []string{args[0]}\n\t\terr = itpUtils.UpdateObject(stub, \"Auction\", keys, buff)\n\t\tif err != nil {\n\t\t\tfmt.Println(\"PostAuctionRequest() : write error while inserting record\\n\")\n\t\t\treturn shim.Error(err.Error())\n\t\t}\n\n\t\t// Post an Item Log and the Auction House ID is included in the log\n\t\t// Recall -- that by default that value is \"DEFAULT\"\n\n\t\tio, err := JSONtoAR(itemObject)\n\t\tresponse := PostItemLog(stub, io, \"ReadyForAuc\", ar.AuctionHouseID, ar.TimeStamp)\n\t\tif response.Status != shim.OK {\n\t\t\tfmt.Println(\"PostItemLog() : write error while inserting record\\n\")\n\t\t\treturn shim.Error(err.Error())\n\t\t}\n\n\t\t//An entry is made in the AuctionInitTable that this Item has been placed for Auction\n\t\t// The UI can pull all items available for auction and the item can be Opened for accepting bids\n\t\t// The 2016 is a dummy key and has notr value other than to get all rows\n\n\t\tkeys = []string{\"2016\", args[0]}\n\t\terr = itpUtils.UpdateObject(stub, \"AucInit\", keys, buff)\n\t\tif err != nil {\n\t\t\tfmt.Println(\"PostAuctionRequest() : write error while inserting record into AucInit\\n\")\n\t\t\treturn shim.Error(err.Error())\n\t\t}\n\n\t}\n\n\treturn shim.Success(buff)\n}\n\nfunc CreateAuctionRequest(args []string) (AuctionRequest, error) {\n\tvar err error\n\tvar aucReg AuctionRequest\n\n\t// Check there are 12 Arguments\n\t// See example -- The Open and Close Dates are Dummy, and will be set by open auction\n\t// '{\"Function\": \"PostAuctionRequest\", \"Args\":[\"1111\", \"AUCREQ\", \"1000\", \"200\", \"100\", \"04012016\", \"1200\", \"1800\",\n\t//   \"INIT\", \"2016-05-20 11:00:00.3 +0000 UTC\",\"2016-05-23 11:00:00.3 +0000 UTC\", \"2016-05-23 11:00:00.3 +0000 UTC\"]}'\n\tif len(args) != 12 {\n\t\tfmt.Println(\"CreateAuctionRegistrationObject(): Incorrect number of arguments. Expecting 11 \")\n\t\treturn aucReg, errors.New(\"CreateAuctionRegistrationObject() : Incorrect number of arguments. Expecting 11 \")\n\t}\n\n\t// Validate UserID is an integer . I think this redundant and can be avoided\n\n\terr = validateID(args[0])\n\tif err != nil {\n\t\treturn aucReg, errors.New(\"CreateAuctionRequest() : User ID should be an integer\")\n\t}\n\n\taucReg = AuctionRequest{args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10], args[11]}\n\tfmt.Println(\"CreateAuctionObject() : Auction Registration : \", aucReg)\n\n\treturn aucReg, nil\n}\n\n//////////////////////////////////////////////////////////\n// Create an Item Transaction record to process Request\n// This is invoked by the CloseAuctionRequest\n//\n//\n////////////////////////////////////////////////////////////\nfunc PostTransaction(stub shim.ChaincodeStubInterface, function string, args []string) pb.Response {\n\n\tif function != \"PostTransaction\" {\n\t\treturn shim.Error(\"PostTransaction(): Invalid function name. Expecting \\\"PostTransaction\\\"\")\n\t}\n\n\tar, err := CreateTransactionRequest(args[0:]) //\n\tif err != nil {\n\t\treturn shim.Error(err.Error())\n\t}\n\n\t// Validate buyer's ID\n\tresponse := ValidateMember(stub, ar.UserId)\n\tif response.Status != shim.OK {\n\t\tfmt.Println(\"PostTransaction() : Failed Buyer not Registered in Blockchain \", ar.UserId)\n\t\treturn shim.Error(err.Error())\n\t}\n\n\tbuyer := response.Payload\n\n\tfmt.Println(\"PostTransaction(): Validated Buyer information successfully \", buyer, ar.UserId)\n\n\t// Validate Item record\n\tresponse = ValidateItemSubmission(stub, ar.ItemID)\n\tif response.Status != shim.OK {\n\t\tfmt.Println(\"PostTransaction() : Failed Could not Validate Item Object in Blockchain \", ar.ItemID)\n\t\treturn shim.Error(err.Error())\n\t}\n\n\tlastUpdatedItemOBCObject := response.Payload\n\tfmt.Println(\"PostTransaction() : Validated Item Object in Blockchain successfully\", ar.ItemID)\n\n\t// Update Item Object with new Owner Key\n\tresponse = UpdateItemObject(stub, lastUpdatedItemOBCObject, ar.HammerPrice, ar.UserId)\n\tnewKey := response.Payload\n\tif response.Status != shim.OK {\n\t\tfmt.Println(\"PostTransaction() : Failed to update Item Master Object in Blockchain \", ar.ItemID)\n\t\treturn shim.Error(err.Error())\n\t} else {\n\t\t// Write New Key to file\n\t\tfmt.Println(\"PostTransaction() : New encryption Key is  \", newKey)\n\t}\n\n\tfmt.Println(\"PostTransaction() : Updated Item Master Object in Blockchain successfully\", ar.ItemID)\n\n\t// Post an Item Log\n\titemObject, err := JSONtoAR(lastUpdatedItemOBCObject)\n\tif err != nil {\n\t\tfmt.Println(\"PostTransaction() : Conversion error JSON to ItemRecord\\n\")\n\t\treturn shim.Error(err.Error())\n\t}\n\n\t// A life cycle event is added to say that the Item is no longer on auction\n\titemObject.ItemBasePrice = ar.HammerPrice\n\titemObject.CurrentOwnerID = ar.UserId\n\n\tresponse = PostItemLog(stub, itemObject, \"NA\", \"DEFAULT\", args[5])\n\tif response.Status != shim.OK {\n\t\tfmt.Println(\"PostTransaction() : write error while inserting item log record\\n\")\n\t\treturn shim.Error(err.Error())\n\t}\n\n\tfmt.Println(\"PostTransaction() : Inserted item log record successfully\", ar.ItemID)\n\n\t// Convert Transaction Object to JSON\n\tbuff, err := TrantoJSON(ar) //\n\tif err != nil {\n\t\tfmt.Println(\"GetObjectBuffer() : Failed to convert Transaction Object to JSON \", args[0])\n\t\treturn shim.Error(err.Error())\n\t}\n\n\t// Update the ledger with the Buffer Data\n\tkeys := []string{args[0], args[3]}\n\terr = itpUtils.UpdateObject(stub, \"Trans\", keys, buff)\n\tif err != nil {\n\t\tfmt.Println(\"PostTransaction() : write error while inserting record\\n\")\n\t\treturn shim.Error(err.Error())\n\t}\n\n\tfmt.Println(\"PostTransaction() : Posted Transaction Record successfully\\n\")\n\n\t// Returns New Key. To get Transaction Details, run GetTransaction\n\n\tsecret_key, _ := json.Marshal(newKey)\n\tfmt.Println(string(secret_key))\n\treturn shim.Success(secret_key)\n\n}\n\nfunc CreateTransactionRequest(args []string) (ItemTransaction, error) {\n\n\tvar at ItemTransaction\n\n\t// Check there are 9 Arguments\n\tif len(args) != 9 {\n\t\tfmt.Println(\"CreateTransactionRequest(): Incorrect number of arguments. Expecting 9 \")\n\t\treturn at, errors.New(\"CreateTransactionRequest() : Incorrect number of arguments. Expecting 9 \")\n\t}\n\n\tat = ItemTransaction{args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]}\n\tfmt.Println(\"CreateTransactionRequest() : Transaction Request: \", at)\n\n\treturn at, nil\n}\n\n///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n// Create a Bid Object\n// Once an Item has been opened for auction, bids can be submitted as long as the auction is \"OPEN\"\n//./peer chaincode invoke -l golang -n mycc -c '{\"Function\": \"PostBid\", \"Args\":[\"1111\", \"BID\", \"1\", \"1000\", \"300\", \"1200\", \"2017-01-23 14:00:00.3 +0000 UTC\"]}'\n//./peer chaincode invoke -l golang -n mycc -c '{\"Function\": \"PostBid\", \"Args\":[\"1111\", \"BID\", \"2\", \"1000\", \"400\", \"3000\",\"2017-01-23 14:00:00.3 +0000 UTC\"]}'\n//\n/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n\nfunc PostBid(stub shim.ChaincodeStubInterface, function string, args []string) pb.Response {\n\n\tbid, err := CreateBidObject(args[0:]) //\n\tif err != nil {\n\t\treturn shim.Error(err.Error())\n\t}\n\n\t// Reject the Bid if the Buyer Information Is not Valid or not registered on the Block Chain\n\tresponse := ValidateMember(stub, args[4])\n\tif response.Status != shim.OK {\n\t\tfmt.Println(\"PostBid() : Failed Buyer not registered on the block-chain \", args[4])\n\t\treturn shim.Error(err.Error())\n\t}\n\n\tbuyerInfo := response.Payload\n\tfmt.Println(\"Buyer information  \", buyerInfo, \"  \", args[4])\n\n\t///////////////////////////////////////\n\t// Reject Bid if Auction is not \"OPEN\"\n\t///////////////////////////////////////\n\tresponse = GetAuctionRequest(stub, \"GetAuctionRequest\", []string{args[0]})\n\tif response.Status != shim.OK {\n\t\tfmt.Println(\"PostBid() : Cannot find Auction record \", args[0])\n\t\treturn shim.Error(\"PostBid(): Cannot find Auction record : \" + args[0])\n\t}\n\n\tRBytes := response.Payload\n\n\taucR, err := JSONtoAucReq(RBytes)\n\tif err != nil {\n\t\tfmt.Println(\"PostBid() : Cannot UnMarshall Auction record\")\n\t\treturn shim.Error(\"PostBid(): Cannot UnMarshall Auction record: \" + args[0])\n\t}\n\n\tif aucR.Status != \"OPEN\" {\n\t\tfmt.Println(\"PostBid() : Cannot accept Bid as Auction is not OPEN \", args[0])\n\t\treturn shim.Error(\"PostBid(): Cannot accept Bid as Auction is not OPEN : \" + args[0])\n\t}\n\n\t///////////////////////////////////////////////////////////////////\n\t// Reject Bid if the time bid was received is > Auction Close Time\n\t///////////////////////////////////////////////////////////////////\n\tif tCompare(bid.BidTime, aucR.CloseDate) == false {\n\t\tfmt.Println(\"PostBid() Failed : BidTime past the Auction Close Time\")\n\t\terror_str := fmt.Sprintf(\"PostBid() Failed : BidTime past the Auction Close Time %s, %s\", bid.BidTime, aucR.CloseDate)\n\t\treturn shim.Error(error_str)\n\t}\n\n\t//////////////////////////////////////////////////////////////////\n\t// Reject Bid if Item ID on Bid does not match Item ID on Auction\n\t//////////////////////////////////////////////////////////////////\n\tif aucR.ItemID != bid.ItemID {\n\t\tfmt.Println(\"PostBid() Failed : Item ID mismatch on bid. Bid Rejected\")\n\t\treturn shim.Error(\"PostBid() : Item ID mismatch on Bid. Bid Rejected\")\n\t}\n\n\t//////////////////////////////////////////////////////////////////////\n\t// Reject Bid if Bid Price is less than Reserve Price\n\t// Convert Bid Price and Reserve Price to Integer (TODO - Float)\n\t//////////////////////////////////////////////////////////////////////\n\tbp, err := strconv.Atoi(bid.BidPrice)\n\tif err != nil {\n\t\tfmt.Println(\"PostBid() Failed : Bid price should be an integer\")\n\t\treturn shim.Error(\"PostBid() : Bid price should be an integer\")\n\t}\n\n\thp, err := strconv.Atoi(aucR.ReservePrice)\n\tif err != nil {\n\t\treturn shim.Error(\"PostItem() : Reserve Price should be an integer\")\n\t}\n\n\t// Check if Bid Price is > Auction Request Reserve Price\n\tif bp < hp {\n\t\treturn shim.Error(\"PostItem() : Bid Price must be greater than Reserve Price\")\n\t}\n\n\t////////////////////////////\n\t// Post or Accept the Bid\n\t////////////////////////////\n\tbuff, err := BidtoJSON(bid) //\n\n\tif err != nil {\n\t\tfmt.Println(\"PostBid() : Failed Cannot create object buffer for write : \", args[1])\n\t\treturn shim.Error(\"PostBid(): Failed Cannot create object buffer for write : \" + args[1])\n\t} else {\n\t\t// Update the ledger with the Buffer Data\n\t\t// err = stub.PutState(args[0], buff)\n\t\tkeys := []string{args[0], args[2]}\n\t\terr = itpUtils.UpdateObject(stub, \"Bid\", keys, buff)\n\t\tif err != nil {\n\t\t\tfmt.Println(\"PostBid() : write error while inserting record\\n\")\n\t\t\treturn shim.Error(err.Error())\n\t\t}\n\t}\n\n\treturn shim.Success(buff)\n}\n\nfunc CreateBidObject(args []string) (Bid, error) {\n\tvar err error\n\tvar aBid Bid\n\n\t// Check there are 7 Arguments\n\t// See example\n\tif len(args) != 7 {\n\t\tfmt.Println(\"CreateBidObject(): Incorrect number of arguments. Expecting 7 \")\n\t\treturn aBid, errors.New(\"CreateBidObject() : Incorrect number of arguments. Expecting 7 \")\n\t}\n\n\t// Validate Bid is an integer\n\n\t_, err = strconv.Atoi(args[0])\n\tif err != nil {\n\t\treturn aBid, errors.New(\"CreateBidObject() : Bid ID should be an integer\")\n\t}\n\n\t_, err = strconv.Atoi(args[2])\n\tif err != nil {\n\t\treturn aBid, errors.New(\"CreateBidObject() : Bid ID should be an integer\")\n\t}\n\n\t// bidTime = args[6]  sent by the client\n\taBid = Bid{args[0], args[1], args[2], args[3], args[4], args[5], args[6]}\n\tfmt.Println(\"CreateBidObject() : Bid Object : \", aBid)\n\n\treturn aBid, nil\n}\n\n//////////////////////////////////////////////////////////\n// JSON To args[] - return a map of the JSON string\n//////////////////////////////////////////////////////////\nfunc JSONtoArgs(Avalbytes []byte) (map[string]interface{}, error) {\n\n\tvar data map[string]interface{}\n\n\tif err := json.Unmarshal(Avalbytes, &data); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn data, nil\n}\n\n//////////////////////////////////////////////////////////\n// Variation of the above - return value from a JSON string\n//////////////////////////////////////////////////////////\n\nfunc GetKeyValue(Avalbytes []byte, key string) string {\n\tvar dat map[string]interface{}\n\tif err := json.Unmarshal(Avalbytes, &dat); err != nil {\n\t\tpanic(err)\n\t}\n\n\tval := dat[key].(string)\n\treturn val\n}\n\n//////////////////////////////////////////////////////////\n// Time and Date Comparison\n// tCompare(\"2016-06-28 18:40:57\", \"2016-06-27 18:45:39\")\n//////////////////////////////////////////////////////////\nfunc tCompare(t1 string, t2 string) bool {\n\n\tlayout := \"2006-01-02 15:04:05\"\n\tbidTime, err := time.Parse(layout, t1)\n\tif err != nil {\n\t\tfmt.Println(\"tCompare() Failed : time Conversion error on t1\")\n\t\treturn false\n\t}\n\n\taucCloseTime, err := time.Parse(layout, t2)\n\tif err != nil {\n\t\tfmt.Println(\"tCompare() Failed : time Conversion error on t2\")\n\t\treturn false\n\t}\n\n\tif bidTime.Before(aucCloseTime) {\n\t\treturn true\n\t}\n\n\treturn false\n}\n\n//////////////////////////////////////////////////////////\n// Converts JSON String to an ART Object\n//////////////////////////////////////////////////////////\nfunc JSONtoAR(data []byte) (ItemObject, error) {\n\n\tar := ItemObject{}\n\terr := json.Unmarshal([]byte(data), &ar)\n\tif err != nil {\n\t\tfmt.Println(\"Unmarshal failed : \", err)\n\t}\n\n\treturn ar, err\n}\n\n//////////////////////////////////////////////////////////\n// Converts an ART Object to a JSON String\n//////////////////////////////////////////////////////////\nfunc ARtoJSON(ar ItemObject) ([]byte, error) {\n\n\tajson, err := json.Marshal(ar)\n\tif err != nil {\n\t\tfmt.Println(err)\n\t\treturn nil, err\n\t}\n\treturn ajson, nil\n}\n\n//////////////////////////////////////////////////////////\n// Converts an BID to a JSON String\n//////////////////////////////////////////////////////////\nfunc ItemLogtoJSON(item ItemLog) ([]byte, error) {\n\n\tajson, err := json.Marshal(item)\n\tif err != nil {\n\t\tfmt.Println(err)\n\t\treturn nil, err\n\t}\n\treturn ajson, nil\n}\n\n//////////////////////////////////////////////////////////\n// Converts an User Object to a JSON String\n//////////////////////////////////////////////////////////\nfunc JSONtoItemLog(ithis []byte) (ItemLog, error) {\n\n\titem := ItemLog{}\n\terr := json.Unmarshal(ithis, &item)\n\tif err != nil {\n\t\tfmt.Println(\"JSONtoAucReq error: \", err)\n\t\treturn item, err\n\t}\n\treturn item, err\n}\n\n//////////////////////////////////////////////////////////\n// Converts an Auction Request to a JSON String\n//////////////////////////////////////////////////////////\nfunc AucReqtoJSON(ar AuctionRequest) ([]byte, error) {\n\n\tajson, err := json.Marshal(ar)\n\tif err != nil {\n\t\tfmt.Println(err)\n\t\treturn nil, err\n\t}\n\treturn ajson, nil\n}\n\n//////////////////////////////////////////////////////////\n// Converts an User Object to a JSON String\n//////////////////////////////////////////////////////////\nfunc JSONtoAucReq(areq []byte) (AuctionRequest, error) {\n\n\tar := AuctionRequest{}\n\terr := json.Unmarshal(areq, &ar)\n\tif err != nil {\n\t\tfmt.Println(\"JSONtoAucReq error: \", err)\n\t\treturn ar, err\n\t}\n\treturn ar, err\n}\n\n//////////////////////////////////////////////////////////\n// Converts an BID to a JSON String\n//////////////////////////////////////////////////////////\nfunc BidtoJSON(myHand Bid) ([]byte, error) {\n\n\tajson, err := json.Marshal(myHand)\n\tif err != nil {\n\t\tfmt.Println(err)\n\t\treturn nil, err\n\t}\n\treturn ajson, nil\n}\n\n//////////////////////////////////////////////////////////\n// Converts an User Object to a JSON String\n//////////////////////////////////////////////////////////\nfunc JSONtoBid(areq []byte) (Bid, error) {\n\n\tmyHand := Bid{}\n\terr := json.Unmarshal(areq, &myHand)\n\tif err != nil {\n\t\tfmt.Println(\"JSONtoAucReq error: \", err)\n\t\treturn myHand, err\n\t}\n\treturn myHand, err\n}\n\n//////////////////////////////////////////////////////////\n// Converts an User Object to a JSON String\n//////////////////////////////////////////////////////////\nfunc UsertoJSON(user UserObject) ([]byte, error) {\n\n\tajson, err := json.Marshal(user)\n\tif err != nil {\n\t\tfmt.Println(\"UsertoJSON error: \", err)\n\t\treturn nil, err\n\t}\n\tfmt.Println(\"UsertoJSON created: \", ajson)\n\treturn ajson, nil\n}\n\n//////////////////////////////////////////////////////////\n// Converts an User Object to a JSON String\n//////////////////////////////////////////////////////////\nfunc JSONtoUser(user []byte) (UserObject, error) {\n\n\tur := UserObject{}\n\terr := json.Unmarshal(user, &ur)\n\tif err != nil {\n\t\tfmt.Println(\"UsertoJSON error: \", err)\n\t\treturn ur, err\n\t}\n\tfmt.Println(\"UsertoJSON created: \", ur)\n\treturn ur, err\n}\n\n//////////////////////////////////////////////////////////\n// Converts an Item Transaction to a JSON String\n//////////////////////////////////////////////////////////\nfunc TrantoJSON(at ItemTransaction) ([]byte, error) {\n\n\tajson, err := json.Marshal(at)\n\tif err != nil {\n\t\tfmt.Println(err)\n\t\treturn nil, err\n\t}\n\treturn ajson, nil\n}\n\n//////////////////////////////////////////////////////////\n// Converts an Trans Object to a JSON String\n//////////////////////////////////////////////////////////\nfunc JSONtoTran(areq []byte) (ItemTransaction, error) {\n\n\tat := ItemTransaction{}\n\terr := json.Unmarshal(areq, &at)\n\tif err != nil {\n\t\tfmt.Println(\"JSONtoTran error: \", err)\n\t\treturn at, err\n\t}\n\treturn at, err\n}\n\n//////////////////////////////////////////////\n// Validates an ID for Well Formed\n//////////////////////////////////////////////\n\nfunc validateID(id string) error {\n\t// Validate UserID is an integer\n\n\t_, err := strconv.Atoi(id)\n\tif err != nil {\n\t\treturn errors.New(\"validateID(): User ID should be an integer\")\n\t}\n\treturn nil\n}\n\n//////////////////////////////////////////////\n// Create an ItemLog from Item\n//////////////////////////////////////////////\n\nfunc ItemToItemLog(io ItemObject, cdt string) ItemLog {\n\n\tiLog := ItemLog{}\n\tiLog.ItemID = io.ItemID\n\tiLog.Status = \"INITIAL\"\n\tiLog.AuctionedBy = \"DEFAULT\"\n\tiLog.RecType = \"ILOG\"\n\tiLog.ItemDesc = io.ItemDesc\n\tiLog.CurrentOwner = io.CurrentOwnerID\n\tiLog.Date = cdt\n\n\treturn iLog\n}\n\n//////////////////////////////////////////////\n// Convert Bid to Transaction for Posting\n//////////////////////////////////////////////\n\nfunc BidtoTransaction(bid Bid) ItemTransaction {\n\n\tvar t ItemTransaction\n\tt.AuctionID = bid.AuctionID\n\tt.RecType = \"POSTTRAN\"\n\tt.ItemID = bid.ItemID\n\tt.TransType = \"SALE\"\n\tt.UserId = bid.BuyerID\n\t// Ideally SystemChain Code must provide a TimeStamp Function\n\tt.TransDate = bid.BidTime\n\tt.HammerTime = bid.BidTime\n\tt.HammerPrice = bid.BidPrice\n\tt.Details = \"The Highest Bidder does not always win\"\n\n\treturn t\n}\n\n////////////////////////////////////////////////////////////////////////////\n// Validate if the User Information Exists\n// in the block-chain\n////////////////////////////////////////////////////////////////////////////\nfunc ValidateMember(stub shim.ChaincodeStubInterface, owner string) pb.Response {\n\n\t// Get the Item Objects and Display it\n\t// Avalbytes, err := stub.GetState(owner)\n\targs := []string{owner}\n\tAvalbytes, err := itpUtils.QueryObject(stub, \"User\", args)\n\n\tif err != nil {\n\t\tfmt.Println(\"ValidateMember() : Failed - Cannot find valid owner record for ART  \", owner)\n\t\tjsonResp := \"{\\\"Error\\\":\\\"Failed to get Owner Object Data for \" + owner + \"\\\"}\"\n\t\treturn shim.Error(jsonResp)\n\t}\n\n\tif Avalbytes == nil {\n\t\tfmt.Println(\"ValidateMember() : Failed - Incomplete owner record for ART  \", owner)\n\t\tjsonResp := \"{\\\"Error\\\":\\\"Failed - Incomplete information about the owner for \" + owner + \"\\\"}\"\n\t\treturn shim.Error(jsonResp)\n\t}\n\n\tfmt.Println(\"ValidateMember() : Validated Item Owner:\\n\", owner)\n\treturn shim.Success(Avalbytes)\n}\n\n////////////////////////////////////////////////////////////////////////////\n// Validate if the User Information Exists\n// in the block-chain\n////////////////////////////////////////////////////////////////////////////\nfunc ValidateItemSubmission(stub shim.ChaincodeStubInterface, artId string) pb.Response {\n\n\t// Get the Item Objects and Display it\n\targs := []string{artId}\n\tAvalbytes, err := itpUtils.QueryObject(stub, \"Item\", args)\n\tif err != nil {\n\t\tfmt.Println(\"ValidateItemSubmission() : Failed - Cannot find valid owner record for ART  \", artId)\n\t\tjsonResp := \"{\\\"Error\\\":\\\"Failed to get Owner Object Data for \" + artId + \"\\\"}\"\n\t\treturn shim.Error(jsonResp)\n\t}\n\n\tif Avalbytes == nil {\n\t\tfmt.Println(\"ValidateItemSubmission() : Failed - Incomplete owner record for ART  \", artId)\n\t\tjsonResp := \"{\\\"Error\\\":\\\"Failed - Incomplete information about the owner for \" + artId + \"\\\"}\"\n\t\treturn shim.Error(jsonResp)\n\t}\n\n\t//fmt.Println(\"ValidateItemSubmission() : Validated Item Owner:\", Avalbytes)\n\treturn shim.Success(Avalbytes)\n}\n\n/////////////////////////////////////////////////////////////////////////////////////////////////////\n// Get List of Bids for an Auction\n// in the block-chain --\n// ./peer chaincode query -l golang -n mycc -c '{\"Function\": \"GetListOfBids\", \"Args\": [\"1111\"]}'\n// ./peer chaincode query -l golang -n mycc -c '{\"Function\": \"GetLastBid\", \"Args\": [\"1111\"]}'\n// ./peer chaincode query -l golang -n mycc -c '{\"Function\": \"GetHighestBid\", \"Args\": [\"1111\"]}'\n/////////////////////////////////////////////////////////////////////////////////////////////////////\nfunc GetListOfBids(stub shim.ChaincodeStubInterface, function string, args []string) pb.Response {\n\n\trs, err := itpUtils.GetList(stub, \"Bid\", args)\n\tif err != nil {\n\t\terror_str := fmt.Sprintf(\"GetListOfBids operation failed. Error marshaling JSON: %s\", err)\n\t\treturn shim.Error(error_str)\n\t}\n\n\tdefer rs.Close()\n\n\t// Iterate through result set\n\tvar i int\n\tvar tlist []Bid // Define a list\n\tfor i = 0; rs.HasNext(); i++ {\n\n\t\t// We can process whichever return value is of interest\n\t\trecord, err := rs.Next()\n\t\tif err != nil {\n\t\t\treturn shim.Success(nil)\n\t\t}\n\t\tbid, err := JSONtoBid(record.Value)\n\t\tif err != nil {\n\t\t\terror_str := fmt.Sprintf(\"GetListOfBids() operation failed - Unmarshall Error. %s\", err)\n\t\t\tfmt.Println(error_str)\n\t\t\treturn shim.Error(error_str)\n\t\t}\n\t\tfmt.Println(\"GetList() : my Value : \", bid)\n\t\ttlist = append(tlist, bid)\n\t}\n\n\tjsonRows, err := json.Marshal(tlist)\n\tif err != nil {\n\t\terror_str := fmt.Sprintf(\"GetListOfBids() operation failed - Unmarshall Error. %s\", err)\n\t\tfmt.Println(error_str)\n\t\treturn shim.Error(error_str)\n\t}\n\n\tfmt.Println(\"List of Bids Requested : \", jsonRows)\n\treturn shim.Success(jsonRows)\n\n}\n\n////////////////////////////////////////////////////////////////////////////////////////////////////////\n// Get List of Auctions that have been initiated\n// in the block-chain\n// This is a fixed Query to be issued as below\n// peer chaincode query -l golang -n mycc -c '{\"Args\": [\"qGetListOfInitAucs\", \"2016\"]}'\n////////////////////////////////////////////////////////////////////////////////////////////////////////\nfunc GetListOfInitAucs(stub shim.ChaincodeStubInterface, function string, args []string) pb.Response {\n\n\trs, err := itpUtils.GetList(stub, \"AucInit\", args)\n\tif err != nil {\n\t\terror_str := fmt.Sprintf(\"GetListOfInitAucs operation failed. Error marshaling JSON: %s\", err)\n\t\treturn shim.Error(error_str)\n\t}\n\n\tdefer rs.Close()\n\n\t// Iterate through result set\n\tvar i int\n\tvar tlist []AuctionRequest // Define a list\n\tfor i = 0; rs.HasNext(); i++ {\n\n\t\t// We can process whichever return value is of interest\n\t\trecord, err := rs.Next()\n\t\tif err != nil {\n\t\t\treturn shim.Success(nil)\n\t\t}\n\t\tar, err := JSONtoAucReq(record.Value)\n\t\tif err != nil {\n\t\t\terror_str := fmt.Sprintf(\"GetListOfInitAucs() operation failed - Unmarshall Error. %s\", err)\n\t\t\tfmt.Println(error_str)\n\t\t\treturn shim.Error(error_str)\n\t\t}\n\t\tfmt.Println(\"GetListOfInitAucs() : my Value : \", ar)\n\t\ttlist = append(tlist, ar)\n\t}\n\n\tjsonRows, err := json.Marshal(tlist)\n\tif err != nil {\n\t\terror_str := fmt.Sprintf(\"GetListOfInitAucs() operation failed - Unmarshall Error. %s\", err)\n\t\tfmt.Println(error_str)\n\t\treturn shim.Error(error_str)\n\t}\n\n\t//fmt.Println(\"List of Auctions Requested : \", jsonRows)\n\treturn shim.Success(jsonRows)\n\n}\n\n////////////////////////////////////////////////////////////////////////////\n// Get List of Open Auctions  for which bids can be supplied\n// in the block-chain\n// This is a fixed Query to be issued as below\n// peer chaincode query -l golang -n mycc -c '{\"Args\": [\"qGetListOfOpenAucs\", \"2016\"]}'\n////////////////////////////////////////////////////////////////////////////\nfunc GetListOfOpenAucs(stub shim.ChaincodeStubInterface, function string, args []string) pb.Response {\n\n\trs, err := itpUtils.GetList(stub, \"AucOpen\", args)\n\tif err != nil {\n\t\terror_str := fmt.Sprintf(\"GetListOfOpenAucs operation failed. Error marshaling JSON: %s\", err)\n\t\treturn shim.Error(error_str)\n\t}\n\tdefer rs.Close()\n\n\t// Iterate through result set\n\tvar i int\n\tvar tlist []AuctionRequest // Define a list\n\tfor i = 0; rs.HasNext(); i++ {\n\n\t\t// We can process whichever return value is of interest\n\t\trecord, err := rs.Next()\n\t\tif err != nil {\n\t\t\treturn shim.Success(nil)\n\t\t}\n\t\tar, err := JSONtoAucReq(record.Value)\n\t\tif err != nil {\n\t\t\terror_str := fmt.Sprintf(\"GetListOfOpenAucs() operation failed - Unmarshall Error. %s\", err)\n\t\t\tfmt.Println(error_str)\n\t\t\treturn shim.Error(error_str)\n\t\t}\n\t\tfmt.Println(\"GetListOfOpenAucs() : my Value : \", ar)\n\t\ttlist = append(tlist, ar)\n\t}\n\n\tjsonRows, err := json.Marshal(tlist)\n\tif err != nil {\n\t\terror_str := fmt.Sprintf(\"GetListOfInitAucs() operation failed - Unmarshall Error. %s\", err)\n\t\tfmt.Println(error_str)\n\t\treturn shim.Error(error_str)\n\t}\n\n\t//fmt.Println(\"List of Open Auctions : \", jsonRows)\n\treturn shim.Success(jsonRows)\n\n}\n\n////////////////////////////////////////////////////////////////////////////\n// Get the Item History for an Item\n// in the block-chain .. Pass the Item ID\n// ./peer chaincode query -l golang -n mycc -c '{\"Function\": \"GetItemLog\", \"Args\": [\"1000\"]}'\n////////////////////////////////////////////////////////////////////////////\nfunc GetItemLog(stub shim.ChaincodeStubInterface, function string, args []string) pb.Response {\n\n\t// Check there are 1 Arguments provided as per the the struct - two are computed\n\t// See example\n\tif len(args) < 1 {\n\t\tfmt.Println(\"GetItemLog(): Incorrect number of arguments. Expecting 1 \")\n\t\tfmt.Println(\"GetItemLog(): ./peer chaincode query -l golang -n mycc -c '{\\\"Function\\\": \\\"GetItem\\\", \\\"Args\\\": [\\\"1111\\\"]}'\")\n\t\treturn shim.Error(\"CreateItemObject(): Incorrect number of arguments. Expecting 12 \")\n\t}\n\n\trs, err := itpUtils.GetList(stub, \"ItemHistory\", args)\n\tif err != nil {\n\t\terror_str := fmt.Sprintf(\"GetItemLog operation failed. Error marshaling JSON: %s\", err)\n\t\treturn shim.Error(error_str)\n\t}\n\n\tdefer rs.Close()\n\n\t// Iterate through result set\n\tvar i int\n\tvar tlist []ItemLog // Define a list\n\tfor i = 0; rs.HasNext(); i++ {\n\n\t\t// We can process whichever return value is of interest\n\t\trecord, err := rs.Next()\n\t\tif err != nil {\n\t\t\treturn shim.Success(nil)\n\t\t}\n\t\til, err := JSONtoItemLog(record.Value)\n\t\tif err != nil {\n\t\t\terror_str := fmt.Sprintf(\"GetItemLog() operation failed - Unmarshall Error. %s\", err)\n\t\t\tfmt.Println(error_str)\n\t\t\treturn shim.Error(error_str)\n\t\t}\n\t\tfmt.Println(\"GetItemLog() : my Value : \", il)\n\t\ttlist = append(tlist, il)\n\t}\n\n\tjsonRows, err := json.Marshal(tlist)\n\tif err != nil {\n\t\terror_str := fmt.Sprintf(\"GetItemLog() operation failed - Unmarshall Error. %s\", err)\n\t\tfmt.Println(error_str)\n\t\treturn shim.Error(error_str)\n\t}\n\n\t//fmt.Println(\"All History : \", jsonRows)\n\treturn shim.Success(jsonRows)\n\n}\n\n////////////////////////////////////////////////////////////////////////////\n// Get a List of Items by Category\n// in the block-chain\n// Input is 2016 + Category\n// Categories include whatever has been defined in the Item Tables - Landscape, Modern, ...\n// See Sample data\n// ./peer chaincode query -l golang -n mycc -c '{\"Function\": \"GetItemListByCat\", \"Args\": [\"2016\", \"Modern\"]}'\n////////////////////////////////////////////////////////////////////////////\nfunc GetItemListByCat(stub shim.ChaincodeStubInterface, function string, args []string) pb.Response {\n\n\t// Check there are 1 Arguments provided as per the the struct - two are computed\n\t// See example\n\tif len(args) < 1 {\n\t\tfmt.Println(\"GetItemListByCat(): Incorrect number of arguments. Expecting 1 \")\n\t\tfmt.Println(\"GetItemListByCat(): ./peer chaincode query -l golang -n mycc -c '{\\\"Function\\\": \\\"GetItemListByCat\\\", \\\"Args\\\": [\\\"Modern\\\"]}'\")\n\t\treturn shim.Error(\"CreateItemObject(): Incorrect number of arguments. Expecting 1 \")\n\t}\n\n\trs, err := itpUtils.GetList(stub, \"ItemCat\", args)\n\tif err != nil {\n\t\terror_str := fmt.Sprintf(\"GetItemListByCat operation failed. Error marshaling JSON: %s\", err)\n\t\treturn shim.Error(error_str)\n\t}\n\n\tdefer rs.Close()\n\n\t// Iterate through result set\n\tvar i int\n\tvar tlist []ItemObject // Define a list\n\tfor i = 0; rs.HasNext(); i++ {\n\n\t\t// We can process whichever return value is of interest\n\t\trecord, err := rs.Next()\n\t\tif err != nil {\n\t\t\treturn shim.Success(nil)\n\t\t}\n\t\tio, err := JSONtoAR(record.Value)\n\t\tif err != nil {\n\t\t\terror_str := fmt.Sprintf(\"GetItemListByCat() operation failed - Unmarshall Error. %s\", err)\n\t\t\tfmt.Println(error_str)\n\t\t\treturn shim.Error(error_str)\n\t\t}\n\n\t\tfmt.Println(\"GetItemListByCat() : my Value : \", io)\n\t\ttlist = append(tlist, io)\n\t}\n\n\tjsonRows, err := json.Marshal(tlist)\n\tif err != nil {\n\t\terror_str := fmt.Sprintf(\"GetItemListByCat() operation failed - Unmarshall Error. %s\", err)\n\t\tfmt.Println(error_str)\n\t\treturn shim.Error(error_str)\n\t}\n\n\t//fmt.Println(\"All Items : \", jsonRows)\n\treturn shim.Success(jsonRows)\n\n}\n\n////////////////////////////////////////////////////////////////////////////\n// Get a List of Users by Category\n// in the block-chain\n////////////////////////////////////////////////////////////////////////////\nfunc GetUserListByCat(stub shim.ChaincodeStubInterface, function string, args []string) pb.Response {\n\n\t// Check there are 1 Arguments provided as per the the struct - two are computed\n\t// See example\n\tif len(args) < 1 {\n\t\tfmt.Println(\"GetUserListByCat(): Incorrect number of arguments. Expecting 1 \")\n\t\tfmt.Println(\"GetUserListByCat(): ./peer chaincode query -l golang -n mycc -c '{\\\"Function\\\": \\\"GetUserListByCat\\\", \\\"Args\\\": [\\\"AH\\\"]}'\")\n\t\treturn shim.Error(\"CreateUserObject(): Incorrect number of arguments. Expecting 1 \")\n\t}\n\n\trs, err := itpUtils.GetList(stub, \"UserCat\", args)\n\tif err != nil {\n\t\terror_str := fmt.Sprintf(\"GetUserListByCat operation failed. Error marshaling JSON: %s\", err)\n\t\treturn shim.Error(error_str)\n\t}\n\n\tdefer rs.Close()\n\n\t// Iterate through result set\n\tvar i int\n\tvar tlist []UserObject // Define a list\n\tfor i = 0; rs.HasNext(); i++ {\n\n\t\t// We can process whichever return value is of interest\n\t\trecord, err := rs.Next()\n\t\tif err != nil {\n\t\t\treturn shim.Success(nil)\n\t\t}\n\t\tuo, err := JSONtoUser(record.Value)\n\t\tif err != nil {\n\t\t\terror_str := fmt.Sprintf(\"GetUserListByCat() operation failed - Unmarshall Error. %s\", err)\n\t\t\tfmt.Println(error_str)\n\t\t\treturn shim.Error(error_str)\n\t\t}\n\n\t\tfmt.Println(\"GetUserListByCat() : my Value : \", uo)\n\t\ttlist = append(tlist, uo)\n\t}\n\n\tjsonRows, err := json.Marshal(tlist)\n\tif err != nil {\n\t\terror_str := fmt.Sprintf(\"GetUserListByCat() operation failed - Unmarshall Error. %s\", err)\n\t\tfmt.Println(error_str)\n\t\treturn shim.Error(error_str)\n\t}\n\n\t//fmt.Println(\"All Users : \", jsonRows)\n\treturn shim.Success(jsonRows)\n\n}\n\n////////////////////////////////////////////////////////////////////////////\n// Get The Highest Bid Received so far for an Auction\n// in the block-chain\n////////////////////////////////////////////////////////////////////////////\nfunc GetLastBid(stub shim.ChaincodeStubInterface, function string, args []string) pb.Response {\n\n\tvar Avalbytes []byte\n\n\tlayout := \"2006-01-02 15:04:05\"\n\thighestTime, err := time.Parse(layout, layout)\n\n\trs, err := itpUtils.GetList(stub, \"Bid\", args)\n\tif err != nil {\n\t\terror_str := fmt.Sprintf(\"GetListOfBids operation failed. Error marshaling JSON: %s\", err)\n\t\treturn shim.Error(error_str)\n\t}\n\n\tdefer rs.Close()\n\t// Iterate through result set\n\n\tfor i := 0; rs.HasNext(); i++ {\n\n\t\t// We can process whichever return value is of interest\n\t\trecord, err := rs.Next()\n\t\tif err != nil {\n\t\t\treturn shim.Success(nil)\n\t\t}\n\t\tcurrentBid, err := JSONtoBid(record.Value)\n\t\tif err != nil {\n\t\t\terror_str := fmt.Sprintf(\"GetHighestBid(0 operation failed. %s\", err)\n\t\t\tfmt.Println(error_str)\n\t\t\treturn shim.Error(error_str)\n\t\t}\n\n\t\tbidTime, err := time.Parse(layout, currentBid.BidTime)\n\t\tif err != nil {\n\t\t\terror_str := fmt.Sprintf(\"GetLastBid() Failed : time Conversion error on BidTime %s\", err)\n\t\t\tfmt.Println(error_str)\n\t\t\treturn shim.Error(error_str)\n\t\t}\n\n\t\tif bidTime.Sub(highestTime) > 0 {\n\t\t\thighestTime = bidTime\n\t\t\tAvalbytes = record.Value\n\t\t}\n\t\treturn shim.Success(Avalbytes)\n\t}\n\treturn shim.Error(\"GetLastBid() : Failed - No Bids Found\")\n}\n\n////////////////////////////////////////////////////////////////////////////\n// Get The Highest Bid Received so far for an Auction\n// in the block-chain\n////////////////////////////////////////////////////////////////////////////\nfunc GetNoOfBidsReceived(stub shim.ChaincodeStubInterface, function string, args []string) pb.Response {\n\n\trs, err := itpUtils.GetList(stub, \"Bid\", args)\n\tif err != nil {\n\t\terror_str := fmt.Sprintf(\"GetListOfBids operation failed. Error marshaling JSON: %s\", err)\n\t\treturn shim.Error(error_str)\n\t}\n\n\tdefer rs.Close()\n\n\t// Iterate through result set\n\tvar i int\n\tfor i = 0; rs.HasNext(); i++ {\n\n\t\t// We can process whichever return value is of interest\n\t\t_, err := rs.Next()\n\t\tif err != nil {\n\t\t\treturn shim.Success(nil)\n\t\t}\n\t}\n\treturn shim.Success([]byte(strconv.Itoa(i)))\n}\n\n////////////////////////////////////////////////////////////////////////////\n// Get the Highest Bid in the List\n//\n////////////////////////////////////////////////////////////////////////////\nfunc GetHighestBid(stub shim.ChaincodeStubInterface, function string, args []string) pb.Response {\n\n\tvar Avalbytes []byte\n\thighestBid := 0\n\trs, err := itpUtils.GetList(stub, \"Bid\", args)\n\tif err != nil {\n\t\terror_str := fmt.Sprintf(\"GetListOfBids operation failed. Error marshaling JSON: %s\", err)\n\t\treturn shim.Error(error_str)\n\t}\n\n\tdefer rs.Close()\n\n\t// Iterate through result set\n\tvar i int\n\tfor i = 0; rs.HasNext(); i++ {\n\n\t\t// We can process whichever return value is of interest\n\t\trecord, err := rs.Next()\n\t\tif err != nil {\n\t\t\treturn shim.Success(nil)\n\t\t}\n\t\tcurrentBid, err := JSONtoBid(record.Value)\n\t\tif err != nil {\n\t\t\terror_str := fmt.Sprintf(\"GetHighestBid(0 operation failed. %s\", err)\n\t\t\tfmt.Println(error_str)\n\t\t\treturn shim.Error(error_str)\n\t\t}\n\n\t\tbidPrice, err := strconv.Atoi(currentBid.BidPrice)\n\t\tif err != nil {\n\t\t\terror_str := fmt.Sprintf(\"GetHighestBid() Int Conversion error on BidPrice! failed. %s\", err)\n\t\t\tfmt.Println(error_str)\n\t\t\treturn shim.Error(error_str)\n\t\t}\n\n\t\tif bidPrice >= highestBid {\n\t\t\thighestBid = bidPrice\n\t\t\tAvalbytes = record.Value\n\n\t\t}\n\t}\n\n\treturn shim.Success(Avalbytes)\n}\n\n///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n// Trigger the Auction\n// Structure of args auctionReqID, RecType, AucStartDateTime, Duration in Minutes ( 3 = 3 minutes)\n// ./peer chaincode invoke -l golang -n mycc -c '{\"Function\": \"OpenAuctionForBids\", \"Args\":[\"1111\", \"OPENAUC\", \"3\", \"2006-01-02 15:04:05\"]}'\n///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n\nfunc OpenAuctionForBids(stub shim.ChaincodeStubInterface, function string, args []string) pb.Response {\n\n\t// Fetch Auction Object and check its Status\n\tAvalbytes, err := itpUtils.QueryObject(stub, \"Auction\", []string{args[0]})\n\tif err != nil {\n\t\tfmt.Println(\"OpenAuctionForBids(): Auction Object Retrieval Failed \")\n\t\treturn shim.Error(\"OpenAuctionForBids(): Auction Object Retrieval Failed \")\n\t}\n\n\taucR, err := JSONtoAucReq(Avalbytes)\n\tif err != nil {\n\t\tfmt.Println(\"OpenAuctionForBids(): Auction Object Unmarshalling Failed \")\n\t\treturn shim.Error(\"OpenAuctionForBids(): Auction Object UnMarshalling Failed \")\n\t}\n\n\tif aucR.Status == \"CLOSED\" {\n\t\tfmt.Println(\"OpenAuctionForBids(): Auction is Closed - Cannot Open for new bids \")\n\t\treturn shim.Error(\"OpenAuctionForBids(): is Closed - Cannot Open for new bids Failed \")\n\t}\n\n\t// Calculate Time Now and Duration of Auction\n\n\t// Validate arg[1]  is an integer as it represents Duration in Minutes\n\taucDuration, err := strconv.Atoi(args[2])\n\tif err != nil {\n\t\tfmt.Println(\"OpenAuctionForBids(): Auction Duration is an integer that represents minute! OpenAuctionForBids() Failed \")\n\t\treturn shim.Error(\"OpenAuctionForBids(): Auction Duration is an integer that represents minute! OpenAuctionForBids() Failed \")\n\t}\n\n\taucStartDate, err := time.Parse(\"2006-01-02 15:04:05\", args[3])\n\taucEndDate := aucStartDate.Add(time.Duration(aucDuration) * time.Minute)\n\n\t// We  don't use go routines anymore to time the auction\n\t//sleepTime := time.Duration(aucDuration * 60 * 1000 * 1000 * 1000)\n\n\t//  Update Auction Object\n\taucR.OpenDate = aucStartDate.Format(\"2006-01-02 15:04:05\")\n\taucR.CloseDate = aucEndDate.Format(\"2006-01-02 15:04:05\")\n\taucR.Status = \"OPEN\"\n\n\tresponse := UpdateAuctionStatus(stub, \"Auction\", aucR)\n\tif response.Status != shim.OK {\n\t\tfmt.Println(\"OpenAuctionForBids(): UpdateAuctionStatus() Failed \")\n\t\treturn shim.Error(\"OpenAuctionForBids(): UpdateAuctionStatus() Failed \")\n\t}\n\n\tbuff := response.Payload\n\n\t// Remove the Auction from INIT Bucket and move to OPEN bucket\n\t// This was designed primarily to help the UI\n\n\tkeys := []string{\"2016\", aucR.AuctionID}\n\terr = itpUtils.DeleteObject(stub, \"AucInit\", keys)\n\tif err != nil {\n\t\tfmt.Println(\"OpenAuctionForBids(): DeleteFromLedger() Failed \")\n\t\treturn shim.Error(\"OpenAuctionForBids(): DeleteFromLedger() Failed \")\n\t}\n\n\t// Add the Auction to Open Bucket\n\terr = itpUtils.UpdateObject(stub, \"AucOpen\", keys, buff)\n\tif err != nil {\n\t\tfmt.Println(\"OpenAuctionForBids() : write error while inserting record into AucInit\\n\")\n\t\treturn shim.Error(err.Error())\n\t}\n\n\treturn shim.Success(buff)\n}\n\n//////////////////////////////////////////////////////////////////////////\n// Close Open Auctions\n// 1. Read OpenAucTable\n// 2. Compare now with expiry time with now\n// 3. If now is > expiry time call CloseAuction\n// ./peer chaincode invoke -l golang -n mycc -c '{\"Function\": \"CloseOpenAuctions\", \"Args\": [\"2016\", \"CLAUC\", currentDateTime]}'\n//////////////////////////////////////////////////////////////////////////\n\nfunc CloseOpenAuctions(stub shim.ChaincodeStubInterface, function string, args []string) pb.Response {\n\n\tresponse := GetListOfOpenAucs(stub, \"AucOpen\", []string{\"2016\"})\n\tif response.Status != shim.OK {\n\t\terror_str := fmt.Sprintf(\"CloseOpenAuctions() operation failed. Error retrieving values from AucOpen: %s\", response.Message)\n\t\tfmt.Println(error_str)\n\t\treturn shim.Error(error_str)\n\t}\n\n\trows := response.Payload\n\ttlist := make([]AuctionRequest, len(rows))\n\terr := json.Unmarshal([]byte(rows), &tlist)\n\tif err != nil {\n\t\terror_str := fmt.Sprintf(\"CloseOpenAuctions() Unmarshal operation failed. Error retrieving values from AucOpen: %s\", response.Message)\n\t\tfmt.Println(error_str)\n\t\treturn shim.Error(error_str)\n\t}\n\n\tfor i := 0; i < len(tlist); i++ {\n\t\tar := tlist[i]\n\n\t\tfmt.Println(\"CloseOpenAuctions() \", ar)\n\n\t\t// Compare Auction Times where args[2] = the CurrentTime sent by the client\n\t\tfmt.Println(\"CloseOpenAuctions() : \", args[2], \": ar.CloseDate : \", ar.CloseDate)\n\t\tif tCompare(args[2], ar.CloseDate) == false {\n\n\t\t\t// Request Closing Auction\n\t\t\tresponse := CloseAuction(stub, \"CloseAuction\", []string{ar.AuctionID})\n\t\t\tif response.Status != shim.OK {\n\t\t\t\terror_str := fmt.Sprintf(\"CloseOpenAuctions() operation failed. %s\", err)\n\t\t\t\tfmt.Println(error_str)\n\t\t\t\treturn shim.Error(error_str)\n\t\t\t}\n\t\t}\n\t}\n\n\treturn shim.Success(nil)\n}\n\n//////////////////////////////////////////////////////////////////////////\n// Close the Auction\n// This is invoked by OpenAuctionForBids\n// which kicks-off a go-routine timer for the duration of the auction\n// When the timer expires, it creates a shell script to CloseAuction() and triggers it\n// This function can also be invoked via CLI - the intent was to close as and when I implement BuyItNow()\n// CloseAuction\n// - Sets the status of the Auction to \"CLOSED\"\n// - Removes the Auction from the Open Auction list (AucOpenTable)\n// - Retrieves the Highest Bid and creates a Transaction\n// - Posts The Transaction\n//\n// To invoke from Command Line via CLI or REST API\n// ./peer chaincode invoke -l golang -n mycc -c '{\"Function\": \"CloseAuction\", \"Args\": [\"1111\", \"AUCREQ\"]}'\n// ./peer chaincode invoke -l golang -n mycc -c '{\"Function\": \"CloseAuction\", \"Args\": [\"1111\", \"AUCREQ\"]}'\n//\n//////////////////////////////////////////////////////////////////////////\n\nfunc CloseAuction(stub shim.ChaincodeStubInterface, function string, args []string) pb.Response {\n\n\t// Close The Auction -  Fetch Auction Object\n\tAvalbytes, err := itpUtils.QueryObject(stub, \"Auction\", []string{args[0]})\n\tif err != nil {\n\t\tfmt.Println(\"CloseAuction(): Auction Object Retrieval Failed \")\n\t\treturn shim.Error(\"CloseAuction(): Auction Object Retrieval Failed \")\n\t}\n\n\taucR, err := JSONtoAucReq(Avalbytes)\n\tif err != nil {\n\t\tfmt.Println(\"CloseAuction(): Auction Object Unmarshalling Failed \")\n\t\treturn shim.Error(\"CloseAuction(): Auction Object UnMarshalling Failed \")\n\t}\n\n\t//  Update Auction Status\n\taucR.Status = \"CLOSED\"\n\tfmt.Println(\"CloseAuction(): UpdateAuctionStatus() successful \", aucR)\n\n\tresponse := UpdateAuctionStatus(stub, \"Auction\", aucR)\n\tif response.Status != shim.OK {\n\t\tfmt.Println(\"CloseAuction(): UpdateAuctionStatus() Failed \")\n\t\treturn shim.Error(\"CloseAuction(): UpdateAuctionStatus() Failed \")\n\t}\n\tAvalbytes = response.Payload\n\n\t// Remove the Auction from Open Bucket\n\tkeys := []string{\"2016\", aucR.AuctionID}\n\terr = itpUtils.DeleteObject(stub, \"AucOpen\", keys)\n\tif err != nil {\n\t\tfmt.Println(\"CloseAuction(): DeleteFromLedger(AucOpenTable) Failed \")\n\t\treturn shim.Error(\"CloseAuction(): DeleteFromLedger(AucOpen) Failed \")\n\t}\n\n\tfmt.Println(\"CloseAuction(): Proceeding to process the highest bid \")\n\n\t// Process Final Bid - Turn it into a Transaction\n\tresponse = GetHighestBid(stub, \"GetHighestBid\", []string{args[0]})\n\tAvalbytes = response.Payload\n\tif Avalbytes == nil {\n\t\tfmt.Println(\"CloseAuction(): No bids available, no change in Item Status - PostTransaction() Completed Successfully \")\n\t\treturn shim.Success(Avalbytes)\n\t}\n\n\tif response.Status != shim.OK {\n\t\tfmt.Println(\"CloseAuction(): No bids available, error encountered - PostTransaction() failed \")\n\t\treturn shim.Error(err.Error())\n\t}\n\n\tbid, _ := JSONtoBid(Avalbytes)\n\tfmt.Println(\"CloseAuction(): Proceeding to process the highest bid \", bid)\n\ttran := BidtoTransaction(bid)\n\tfmt.Println(\"CloseAuction(): Converting Bid to tran \", tran)\n\n\t// Process the last bid once Time Expires\n\ttranArgs := []string{tran.AuctionID, tran.RecType, tran.ItemID, tran.TransType, tran.UserId, tran.TransDate, tran.HammerTime, tran.HammerPrice, tran.Details}\n\tfmt.Println(\"CloseAuction(): Proceeding to process the  Transaction \", tranArgs)\n\n\tresponse = PostTransaction(stub, \"PostTransaction\", tranArgs)\n\tif response.Status != shim.OK {\n\t\tfmt.Println(\"CloseAuction(): PostTransaction() Failed \")\n\t\treturn shim.Error(\"CloseAuction(): PostTransaction() Failed \")\n\t}\n\tAvalbytes = response.Payload\n\tfmt.Println(\"CloseAuction(): PostTransaction() Completed Successfully \")\n\treturn shim.Success(Avalbytes)\n\n}\n\n////////////////////////////////////////////////////////////////////////////////////////////\n// Buy It Now\n// Rules:\n// If Buy IT Now Option is available then a Buyer has the option to buy the ITEM\n// before the bids exceed BuyITNow Price . Normally, The application should take of this\n// at the UI level and this chain-code assumes application has validated that\n////////////////////////////////////////////////////////////////////////////////////////////\n\nfunc BuyItNow(stub shim.ChaincodeStubInterface, function string, args []string) pb.Response {\n\n\t// Process Final Bid - Turn it into a Transaction\n\tresponse := GetHighestBid(stub, \"GetHighestBid\", []string{args[0]})\n\tbid, err := JSONtoBid(response.Payload)\n\tif err != nil {\n\t\treturn shim.Error(\"BuyItNow() : JSONtoBid Error\")\n\t}\n\n\t// Check if BuyItNow Price > Highest Bid so far\n\tbinP, err := strconv.Atoi(args[5])\n\tif err != nil {\n\t\treturn shim.Error(\"BuyItNow() : Invalid BuyItNow Price\")\n\t}\n\n\thbP, err := strconv.Atoi(bid.BidPrice)\n\tif err != nil {\n\t\treturn shim.Error(\"BuyItNow() : Invalid Highest Bid Price\")\n\t}\n\n\tif hbP > binP {\n\t\treturn shim.Error(\"BuyItNow() : Highest Bid Price > BuyItNow Price - BuyItNow Rejected\")\n\t}\n\n\t// Close The Auction -  Fetch Auction Object\n\tAvalbytes, err := itpUtils.QueryObject(stub, \"Auction\", []string{args[0]})\n\tif err != nil {\n\t\tfmt.Println(\"BuyItNow(): Auction Object Retrieval Failed \")\n\t\treturn shim.Error(\"BuyItNow(): Auction Object Retrieval Failed \")\n\t}\n\n\taucR, err := JSONtoAucReq(Avalbytes)\n\tif err != nil {\n\t\tfmt.Println(\"BuyItNow(): Auction Object Unmarshalling Failed \")\n\t\treturn shim.Error(\"BuyItNow(): Auction Object UnMarshalling Failed \")\n\t}\n\n\t//  Update Auction Status\n\taucR.Status = \"CLOSED\"\n\tfmt.Println(\"BuyItNow(): UpdateAuctionStatus() successful \", aucR)\n\n\tresponse = UpdateAuctionStatus(stub, \"Auction\", aucR)\n\tif response.Status != shim.OK {\n\t\tfmt.Println(\"BuyItNow(): UpdateAuctionStatus() Failed \")\n\t\treturn shim.Error(\"BuyItNow(): UpdateAuctionStatus() Failed \")\n\t}\n\tAvalbytes = response.Payload\n\n\t// Remove the Auction from Open Bucket\n\tkeys := []string{\"2016\", aucR.AuctionID}\n\terr = itpUtils.DeleteObject(stub, \"AucOpen\", keys)\n\tif err != nil {\n\t\tfmt.Println(\"BuyItNow(): DeleteFromLedger(AucOpen) Failed \")\n\t\treturn shim.Error(\"BuyItNow(): DeleteFromLedger(AucOpen) Failed \")\n\t}\n\n\tfmt.Println(\"BuyItNow(): Proceeding to process the highest bid \")\n\n\t// Convert the BuyITNow to a Bid type struct\n\tbuyItNowBid, err := CreateBidObject(args[0:])\n\tif err != nil {\n\t\treturn shim.Error(err.Error())\n\t}\n\n\t// Reject the offer if the Buyer Information Is not Valid or not registered on the Block Chain\n\tresponse = ValidateMember(stub, args[4])\n\tif response.Status != shim.OK {\n\t\tfmt.Println(\"BuyItNow() : Failed Buyer not registered on the block-chain \", args[4])\n\t\treturn shim.Error(err.Error())\n\t}\n\n\tbuyerInfo := response.Payload\n\tfmt.Println(\"Buyer information  \", buyerInfo, args[4])\n\n\ttran := BidtoTransaction(buyItNowBid)\n\tfmt.Println(\"BuyItNow(): Converting Bid to tran \", tran)\n\n\t// Process the buy-it-now offer\n\ttranArgs := []string{tran.AuctionID, tran.RecType, tran.ItemID, tran.TransType, tran.UserId, tran.TransDate, tran.HammerTime, tran.HammerPrice, tran.Details}\n\tfmt.Println(\"BuyItNow(): Proceeding to process the  Transaction \", tranArgs)\n\n\tresponse = PostTransaction(stub, \"PostTransaction\", tranArgs)\n\tif response.Status != shim.OK {\n\t\tfmt.Println(\"BuyItNow(): PostTransaction() Failed \")\n\t\treturn shim.Error(\"CloseAuction(): PostTransaction() Failed \")\n\t}\n\n\tfmt.Println(\"BuyItNow(): PostTransaction() Completed Successfully \")\n\treturn response\n}\n\n//////////////////////////////////////////////////////////////////////////\n// Update the Auction Object\n// This function updates the status of the auction\n// from INIT to OPEN to CLOSED\n//////////////////////////////////////////////////////////////////////////\n\nfunc UpdateAuctionStatus(stub shim.ChaincodeStubInterface, tableName string, ar AuctionRequest) pb.Response {\n\n\tbuff, err := AucReqtoJSON(ar)\n\tif err != nil {\n\t\tfmt.Println(\"UpdateAuctionStatus() : Failed Cannot create object buffer for write : \", ar.AuctionID)\n\t\treturn shim.Error(\"UpdateAuctionStatus(): Failed Cannot create object buffer for write : \" + ar.AuctionID)\n\t}\n\n\t// Update the ledger with the Buffer Data\n\t//keys := []string{ar.AuctionID, ar.ItemID}\n\tkeys := []string{ar.AuctionID}\n\terr = itpUtils.ReplaceObject(stub, \"Auction\", keys, buff)\n\tif err != nil {\n\t\tfmt.Println(\"UpdateAuctionStatus() : write error while inserting record\\n\")\n\t\treturn shim.Error(err.Error())\n\t}\n\treturn shim.Success(buff)\n}\n\n/////////////////////////////////////////////////////////////////////////////////////////////\n// Return the right Object Buffer after validation to write to the ledger\n// var recType = []string{\"ARTINV\", \"USER\", \"BID\", \"AUCREQ\", \"POSTTRAN\", \"OPENAUC\", \"CLAUC\"}\n/////////////////////////////////////////////////////////////////////////////////////////////\n\nfunc ProcessQueryResult(stub shim.ChaincodeStubInterface, Avalbytes []byte, args []string) error {\n\n\t// Identify Record Type by scanning the args for one of the recTypes\n\t// This is kind of a post-processor once the query fetches the results\n\t// RecType is the style of programming in the punch card days ..\n\t// ... well\n\n\tvar dat map[string]interface{}\n\n\tif err := json.Unmarshal(Avalbytes, &dat); err != nil {\n\t\tpanic(err)\n\t}\n\n\tvar recType string\n\trecType = dat[\"RecType\"].(string)\n\tswitch recType {\n\n\tcase \"ARTINV\":\n\n\t\tar, err := JSONtoAR(Avalbytes) //\n\t\tif err != nil {\n\t\t\tfmt.Println(\"ProcessRequestType(): Cannot create itemObject \\n\")\n\t\t\treturn err\n\t\t}\n\t\t// Decrypt Image and Save Image in a file\n\t\timage := itpUtils.Decrypt(ar.AES_Key, ar.ItemImage)\n\t\tif err != nil {\n\t\t\tfmt.Println(\"ProcessRequestType() : Image decrytion failed \")\n\t\t\treturn err\n\t\t}\n\t\tfmt.Println(\"ProcessRequestType() : Image conversion from byte[] to file successfull \")\n\t\terr = itpUtils.ByteArrayToImage(image, \"copy.\"+ar.ItemPicFN)\n\t\tif err != nil {\n\n\t\t\tfmt.Println(\"ProcessRequestType() : Image conversion from byte[] to file failed \")\n\t\t\treturn err\n\t\t}\n\t\treturn err\n\n\tcase \"USER\":\n\t\tur, err := JSONtoUser(Avalbytes) //\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tfmt.Println(\"ProcessRequestType() : \", ur)\n\t\treturn err\n\n\tcase \"AUCREQ\":\n\t\tar, err := JSONtoAucReq(Avalbytes) //\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tfmt.Println(\"ProcessRequestType() : \", ar)\n\t\treturn err\n\n\tcase \"OPENAUC\":\n\t\tar, err := JSONtoAucReq(Avalbytes) //\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tfmt.Println(\"ProcessRequestType() : \", ar)\n\t\treturn err\n\tcase \"CLAUC\":\n\t\tar, err := JSONtoAucReq(Avalbytes) //\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tfmt.Println(\"ProcessRequestType() : \", ar)\n\t\treturn err\n\tcase \"POSTTRAN\":\n\t\tatr, err := JSONtoTran(Avalbytes) //\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tfmt.Println(\"ProcessRequestType() : \", atr)\n\t\treturn err\n\tcase \"BID\":\n\t\tbid, err := JSONtoBid(Avalbytes) //\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tfmt.Println(\"ProcessRequestType() : \", bid)\n\t\treturn err\n\tcase \"DEFAULT\":\n\t\treturn nil\n\tcase \"XFER\":\n\t\treturn nil\n\tdefault:\n\t\treturn errors.New(\"Unknown\")\n\t}\n\treturn nil\n\n}\n"
  },
  {
    "path": "art/artchaincode/vendor/itpUtils/image_proc_0.6api.go",
    "content": "/******************************************************************\nLicensed to the Apache Software Foundation (ASF) under one\nor more contributor license agreements.  See the NOTICE file\ndistributed with this work for additional information\nregarding copyright ownership.  The ASF licenses this file\nto you under the Apache License, Version 2.0 (the\n\"License\"); you may not use this file except in compliance\nwith the License.  You may obtain a copy of the License at\n\n  http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing,\nsoftware distributed under the License is distributed on an\n\"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\nKIND, either express or implied.  See the License for the\nspecific language governing permissions and limitations\nunder the License.\n******************************************************************/\n\n///////////////////////////////////////////////////////////////////////\n// Author : Mohan Venkataraman\n// Purpose: Explore the Hyperledger/fabric and understand\n// how to write an chain code, application/chain code boundaries\n// The code is not the best as it has just hammered out in a day or two\n// Feedback and updates are appreciated\n///////////////////////////////////////////////////////////////////////\n\npackage itpUtils \n\nimport (\n\t\"bufio\"\n\t\"bytes\"\n\t\"crypto/aes\"\n\t\"crypto/cipher\"\n\t\"crypto/rand\"\n\t\"errors\"\n\t\"fmt\"\n\t\"image\"\n\t\"image/gif\"\n\t\"image/jpeg\"\n\t\"image/png\"\n\t\"io\"\n\t\"net/http\"\n\t\"os\"\n)\n\n\n///////////////////////////////////////////////////////////\n// Convert Image to []bytes and viceversa\n// Detect Image Filetype\n// Image Function to read an image and create a byte array\n// Currently only PNG images are supported\n///////////////////////////////////////////////////////////\nfunc ImageToByteArray(imageFile string) ([]byte, string) {\n\n\tfile, err := os.Open(imageFile)\n\n\tif err != nil {\n\t\tfmt.Println(\"imageToByteArray() : cannot OPEN image file \", err)\n\t\treturn nil, string(\"imageToByteArray() : cannot OPEN image file \")\n\t}\n\n\tdefer file.Close()\n\n\tfileInfo, _ := file.Stat()\n\tvar size int64 = fileInfo.Size()\n\tbytes := make([]byte, size)\n\n\t// read file into bytes\n\tbuff := bufio.NewReader(file)\n\t_, err = buff.Read(bytes)\n\n\tif err != nil {\n\t\tfmt.Println(\"imageToByteArray() : cannot READ image file\")\n\t\treturn nil, string(\"imageToByteArray() : cannot READ image file \")\n\t}\n\n\tfiletype := http.DetectContentType(bytes)\n\tfmt.Println(\"imageToByteArray() : \", filetype)\n\t//filetype := GetImageType(bytes)\n\n\treturn bytes, filetype\n}\n\n//////////////////////////////////////////////////////\n// If Valid fileType, will have \"image\" as first word\n//////////////////////////////////////////////////////\nfunc GetImageType(buff []byte) string {\n\tfiletype := http.DetectContentType(buff)\n\n\tswitch filetype {\n\tcase \"image/jpeg\", \"image/jpg\":\n\t\treturn filetype\n\n\tcase \"image/gif\":\n\t\treturn filetype\n\n\tcase \"image/png\":\n\t\treturn filetype\n\n\tcase \"application/pdf\": // not image, but application !\n\t\tfiletype = \"application/pdf\"\n\tdefault:\n\t\tfiletype = \"Unknown\"\n\t}\n\treturn filetype\n}\n\n////////////////////////////////////////////////////////////\n// Converts a byteArray into an image and saves it\n// into an appropriate file\n// It is important to get the file type before saving the\n// file by call the GetImageType\n////////////////////////////////////////////////////////////\nfunc ByteArrayToImage(imgByte []byte, imageFile string) error {\n\n\t// convert []byte to image for saving to file\n\timg, _, _ := image.Decode(bytes.NewReader(imgByte))\n\n\tfmt.Println(\"ProcessQueryResult ByteArrayToImage : proceeding to create image \")\n\n\t//save the imgByte to file\n\tout, err := os.Create(imageFile)\n\n\tif err != nil {\n\t\tfmt.Println(\"ByteArrayToImage() : cannot CREATE image file \", err)\n\t\treturn errors.New(\"ByteArrayToImage() : cannot CREATE image file \")\n\t}\n\tfmt.Println(\"ProcessRequestType ByteArrayToImage : proceeding to Encode image \")\n\n\t//err = png.Encode(out, img)\n\tfiletype := http.DetectContentType(imgByte)\n\n\tswitch filetype {\n\tcase \"image/jpeg\", \"image/jpg\":\n\t\tvar opt jpeg.Options\n\t\topt.Quality = 100\n\t\terr = jpeg.Encode(out, img, &opt)\n\n\tcase \"image/gif\":\n\t\tvar opt gif.Options\n\t\topt.NumColors = 256\n\t\terr = gif.Encode(out, img, &opt)\n\n\tcase \"image/png\":\n\t\terr = png.Encode(out, img)\n\n\tdefault:\n\t\terr = errors.New(\"Only PMNG, JPG and GIF Supported \")\n\t}\n\n\tif err != nil {\n\t\tfmt.Println(\"ByteArrayToImage() : cannot ENCODE image file \", err)\n\t\treturn errors.New(\"ByteArrayToImage() : cannot ENCODE image file \")\n\t}\n\n\t// everything ok\n\tfmt.Println(\"Image file  generated and saved to \", imageFile)\n\treturn nil\n}\n\n///////////////////////////////////////////////////////////////////////\n// Encryption and Decryption Section\n// Images will be Encrypted and stored and the key will be part of the\n// certificate that is provided to the Owner\n///////////////////////////////////////////////////////////////////////\n\nconst (\n\tAESKeyLength = 32 // AESKeyLength is the default AES key length\n\tNonceSize    = 24 // NonceSize is the default NonceSize\n)\n\n///////////////////////////////////////////////////\n// GetRandomBytes returns len random looking bytes\n///////////////////////////////////////////////////\nfunc GetRandomBytes(len int) ([]byte, error) {\n\tkey := make([]byte, len)\n\n\t_, err := rand.Read(key)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn key, nil\n}\n\n////////////////////////////////////////////////////////////\n// GenAESKey returns a random AES key of length AESKeyLength\n// 3 Functions to support Encryption and Decryption\n// GENAESKey() - Generates AES symmetric key\n// Encrypt() Encrypts a [] byte\n// Decrypt() Decryts a [] byte\n////////////////////////////////////////////////////////////\nfunc GenAESKey() ([]byte, error) {\n\treturn GetRandomBytes(AESKeyLength)\n}\n\nfunc PKCS5Pad(src []byte) []byte {\n\tpadding := aes.BlockSize - len(src)%aes.BlockSize\n\tpad := bytes.Repeat([]byte{byte(padding)}, padding)\n\treturn append(src, pad...)\n}\n\nfunc PKCS5Unpad(src []byte) []byte {\n\tlen := len(src)\n\tunpad := int(src[len-1])\n\treturn src[:(len - unpad)]\n}\n\nfunc Decrypt(key []byte, ciphertext []byte) []byte {\n\n\t// Create the AES cipher\n\tblock, err := aes.NewCipher(key)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\t// Before even testing the decryption,\n\t// if the text is too small, then it is incorrect\n\tif len(ciphertext) < aes.BlockSize {\n\t\tpanic(\"Text is too short\")\n\t}\n\n\t// Get the 16 byte IV\n\tiv := ciphertext[:aes.BlockSize]\n\n\t// Remove the IV from the ciphertext\n\tciphertext = ciphertext[aes.BlockSize:]\n\n\t// Return a decrypted stream\n\tstream := cipher.NewCFBDecrypter(block, iv)\n\n\t// Decrypt bytes from ciphertext\n\tstream.XORKeyStream(ciphertext, ciphertext)\n\n\treturn ciphertext\n}\n\nfunc Encrypt(key []byte, ba []byte) []byte {\n\n\t// Create the AES cipher\n\tblock, err := aes.NewCipher(key)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\t// Empty array of 16 + ba length\n\t// Include the IV at the beginning\n\tciphertext := make([]byte, aes.BlockSize+len(ba))\n\n\t// Slice of first 16 bytes\n\tiv := ciphertext[:aes.BlockSize]\n\n\t// Write 16 rand bytes to fill iv\n\tif _, err := io.ReadFull(rand.Reader, iv); err != nil {\n\t\tpanic(err)\n\t}\n\n\t// Return an encrypted stream\n\tstream := cipher.NewCFBEncrypter(block, iv)\n\n\t// Encrypt bytes from ba to ciphertext\n\tstream.XORKeyStream(ciphertext[aes.BlockSize:], ba)\n\n\treturn ciphertext\n}\n\n"
  },
  {
    "path": "art/artchaincode/vendor/itpUtils/table_1.0api.go",
    "content": "/******************************************************************\nCopyright IT People Corp. 2017 All Rights Reserved.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n                 http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n\n******************************************************************/\n\n///////////////////////////////////////////////////////////////////////\n// Author : IT People - Mohan - table API for v1.0\n// Enable CouchDb as the database..\n// Purpose: Explore the Hyperledger/fabric and understand\n// how to write an chain code, application/chain code boundaries\n// The code is not the best as it has just hammered out in a day or two\n// Feedback and updates are appreciated\n///////////////////////////////////////////////////////////////////////\n\npackage itpUtils\n\nimport (\n\t\"errors\"\n        \"bytes\"\n\t\"fmt\"\n\t\"github.com/hyperledger/fabric/core/chaincode/shim\"\n)\n\n//////////////////////////////////////////////////////////////////////////////////////////////////\n// The recType is a mandatory attribute. The original app was written with a single table\n// in mind. The only way to know how to process a record was the 70's style 80 column punch card\n// which used a record type field. The array below holds a list of valid record types.\n// This could be stored on a blockchain table or an application\n//////////////////////////////////////////////////////////////////////////////////////////////////\nvar recType = []string{\"ARTINV\", \"USER\", \"BID\", \"AUCREQ\", \"POSTTRAN\", \"OPENAUC\", \"CLAUC\", \"XFER\", \"VERIFY\"}\n\n//////////////////////////////////////////////////////////////////////////////////////////////////\n// The following array holds the list of tables that should be created\n// The deploy/init deletes the tables and recreates them every time a deploy is invoked\n//////////////////////////////////////////////////////////////////////////////////////////////////\nvar Objects = []string{\"PARTY\", \"CASHTXN\", \"User\", \"UserCat\", \"Item\", \"ItemCat\", \"ItemHistory\", \"Auction\", \"AucInit\", \"AucOpen\", \"Bid\", \"Trans\"}\n\n/////////////////////////////////////////////////////////////////////////////////////////////////////\n// A Map that holds ObjectNames and the number of Keys\n// This information is used to dynamically Create, Update\n// Replace , and Query the Ledger\n// In this model all attributes in a table are strings\n// The chain code does both validation\n// A dummy key like 2016 in some cases is used for a query to get all rows\n//\n//              \"User\":        1, Key: UserID\n//              \"Item\":        1, Key: ItemID\n//              \"UserCat\":     3, Key: \"2016\", UserType, UserID\n//              \"ItemCat\":     3, Key: \"2016\", ItemSubject, ItemID\n//              \"Auction\":     1, Key: AuctionID\n//              \"AucInit\":     2, Key: Year, AuctionID\n//              \"AucOpen\":     2, Key: Year, AuctionID\n//              \"Trans\":       2, Key: AuctionID, ItemID\n//              \"Bid\":         2, Key: AuctionID, BidNo\n//              \"ItemHistory\": 4, Key: ItemID, Status, AuctionHouseID(if applicable),date-time\n//\n// The additional key is the ObjectType (aka ObjectName or Object). The keys  would be\n// keys: {\"User\", UserId} or keys: {\"AuctInit\", \"2016\", \"1134\"}\n/////////////////////////////////////////////////////////////////////////////////////////////////////\n\nfunc GetNumberOfKeys(tname string) int {\n\tObjectMap := map[string]int{\n\t\t\"User\":        1,\n\t\t\"Item\":        1,\n\t\t\"UserCat\":     3,\n\t\t\"ItemCat\":     3,\n\t\t\"Auction\":     1,\n\t\t\"AucInit\":     2,\n\t\t\"AucOpen\":     2,\n\t\t\"Trans\":       2,\n\t\t\"Bid\":         2,\n\t\t\"ItemHistory\": 4,\n                \"PARTY\":       2,\n                \"CASHTXN\":     1,\n\t}\n\treturn ObjectMap[tname]\n}\n\n/////////////////////////////////////////////////////////////////\n// This function checks the incoming args for a valid record\n// type entry as per the declared array recType[]\n// The rectType attribute can be anywhere in the args or struct\n// not necessarily in args[1] as per my old logic\n// The Request type is used to direct processing\n// the record accordingly e: recType is \"USER\"\n// \"Args\":[\"PostUser\",\"100\", \"USER\", \"Ashley Hart\", \"TRD\",  \"Morrisville Parkway, #216, Morrisville, NC 27560\",\n//         \"9198063535\", \"ashley@it people.com\", \"SUNTRUST\", \"0001732345\", \"0234678\", \"2017-01-02 15:04:05\"]}'\n/////////////////////////////////////////////////////////////////\nfunc ChkRecType(args []string) bool {\n        for _, rt := range args {\n                for _, val := range recType {\n                        if val == rt {\n                                return true\n                        }\n                }\n        }\n        return false\n}\n\n/////////////////////////////////////////////////////////////////\n// Checks if the incoming invoke has a valid requesType\n// The Request type is used to process the record accordingly\n// Old Logic (see new logic up)\n/////////////////////////////////////////////////////////////////\nfunc CheckRecType(rt string) bool {\n        for _, val := range recType {\n                if val == rt {\n                        fmt.Println(\"CheckRequestType() : Valid Request Type , val : \", val, rt, \"\\n\")\n                        return true\n                }\n        }\n        fmt.Println(\"CheckRequestType() : Invalid Request Type , val : \", rt, \"\\n\")\n        return false\n}\n\n/////////////////////////////////////////////////////////////////\n// Checks if the args contain a valid Record Type. Typically, this\n// model expects the Object Type to be args[2] but\n// for the sake of flexibility, it scans the input data for\n// a valid type if available\n/////////////////////////////////////////////////////////////////\nfunc IdentifyRecType(args []string) (string, error) {\n        for _, rt := range args {\n                for _, val := range recType {\n                        if val == rt {\n                                return rt, nil\n                        }\n                }\n        }\n        return \"\", fmt.Errorf(\"IdentifyRecType: Not Found\")\n}\n\n/////////////////////////////////////////////////////////////////\n// Checks if the args contain a valid Object Type. Typically, this\n// model expects the Object Type to be args[0] but\n// for the sake of flexibility, it scans the input data for\n// a valid type if available\n/////////////////////////////////////////////////////////////////\nfunc IdentifyObjectType(args []string) (string, error) {\n        for _, rt := range args {\n                for _, val := range Objects {\n                        if val == rt {\n                                return rt, nil\n                        }\n                }\n        }\n        return  \"\", fmt.Errorf(\"IdentifyObjectType: Object Not Found\")\n}\n\n////////////////////////////////////////////////////////////////////////////\n// Open a Ledgers if one does not exist\n// These ledgers will be used to write /  read data\n////////////////////////////////////////////////////////////////////////////\nfunc InitObject(stub shim.ChaincodeStubInterface, objectType string, keys []string)  error {\n\n\tfmt.Println(\">> Not Implemented Yet << Initializing Object : \" , objectType, \" Keys: \", keys)\n\treturn nil\n}\n\n////////////////////////////////////////////////////////////////////////////\n// Update the Object - Replace current data with replacement\n// Register users into this table\n////////////////////////////////////////////////////////////////////////////\nfunc UpdateObject(stub shim.ChaincodeStubInterface, objectType string, keys []string, objectData []byte) error {\n\n        // Check how many keys\n\n        err := VerifyAtLeastOneKeyIsPresent(objectType, keys )\n        if err != nil {\n                return err\n        }\n\n\t// Convert keys to  compound key\n\tcompositeKey, _ := stub.CreateCompositeKey(objectType, keys)\n\n\t// Add Object JSON to state\n\terr = stub.PutState(compositeKey, objectData)\n\tif err != nil {\n\t\tfmt.Println(\"UpdateObject() : Error inserting Object into State Database %s\", err)\n\t\treturn err\n\t}\n\n\treturn nil\n\n}\n\n////////////////////////////////////////////////////////////////////////////////////////////////////////////\n// Retrieve the object based on the key and simply delete it\n//\n////////////////////////////////////////////////////////////////////////////////////////////////////////////\nfunc DeleteObject(stub shim.ChaincodeStubInterface, objectType string, keys []string) error {\n\n        // Check how many keys\n\n        err := VerifyAtLeastOneKeyIsPresent(objectType, keys )\n        if err != nil {\n                return err\n        }\n\n\t// Convert keys to  compound key\n\tcompositeKey, _ := stub.CreateCompositeKey(objectType, keys)\n\n\t// Remove object from the State Database\n\terr = stub.DelState(compositeKey)\n\tif err != nil {\n\t\tfmt.Println(\"DeleteObject() : Error deleting Object into State Database %s\", err)\n\t\treturn err\n\t}\n\tfmt.Println(\"DeleteObject() : \", \"Object : \" , objectType, \" Key : \", compositeKey)\n\n\treturn nil\n}\n\n////////////////////////////////////////////////////////////////////////////////////////////////////////////\n// Delete all objects of ObjectType\n//\n////////////////////////////////////////////////////////////////////////////////////////////////////////////\nfunc DeleteAllObjects(stub shim.ChaincodeStubInterface, objectType string) error {\n\n\n        // Convert keys to  compound key\n        compositeKey, _ := stub.CreateCompositeKey(objectType, []string{\"\"})\n\n        // Remove object from the State Database\n        err := stub.DelState(compositeKey)\n        if err != nil {\n                fmt.Println(\"DeleteAllObjects() : Error deleting all Object into State Database %s\", err)\n\t\treturn err\n        }\n        fmt.Println(\"DeleteObject() : \", \"Object : \" , objectType, \" Key : \", compositeKey)\n\n        return nil\n}\n\n////////////////////////////////////////////////////////////////////////////////////////////////////////////\n// Replaces the Entry in the Ledger\n// The existing object is simply queried and the data contents is replaced with\n// new content\n////////////////////////////////////////////////////////////////////////////////////////////////////////////\nfunc ReplaceObject(stub shim.ChaincodeStubInterface, objectType string, keys []string, objectData []byte) error {\n\n        // Check how many keys\n\n        err := VerifyAtLeastOneKeyIsPresent(objectType, keys )\n        if err != nil {\n                return err\n        }\n\n\t// Convert keys to  compound key\n\tcompositeKey, _ := stub.CreateCompositeKey(objectType, keys)\n\n\t// Add Party JSON to state\n\terr = stub.PutState(compositeKey, objectData)\n\tif err != nil {\n\t\tfmt.Println(\"ReplaceObject() : Error replacing Object in State Database %s\", err)\n\t\treturn err\n\t}\n\n\tfmt.Println(\"ReplaceObject() : - end init object \", objectType)\n\treturn nil\n}\n\n////////////////////////////////////////////////////////////////////////////\n// Query a User Object by Object Name and Key\n// This has to be a full key and should return only one unique object\n////////////////////////////////////////////////////////////////////////////\nfunc QueryObject(stub shim.ChaincodeStubInterface, objectType string, keys []string) ([]byte, error) {\n\n        // Check how many keys\n\n        err := VerifyAtLeastOneKeyIsPresent(objectType, keys )\n        if err != nil {\n                return nil, err\n        }\n\n        compoundKey, _ := stub.CreateCompositeKey(objectType, keys)\n        fmt.Println(\"QueryObject() : Compound Key : \", compoundKey)\n\n        Avalbytes, err := stub.GetState(compoundKey)\n        if err != nil {\n                return nil, err\n        }\n\n        return Avalbytes, nil\n}\n\n////////////////////////////////////////////////////////////////////////////\n// Query a User Object by Object Name and Key\n// This has to be a full key and should return only one unique object\n////////////////////////////////////////////////////////////////////////////\nfunc QueryObjectWithProcessingFunction(stub shim.ChaincodeStubInterface, objectType string, keys []string, fname func(shim.ChaincodeStubInterface, []byte, []string)(error)) ([]byte, error) {\n\n        // Check how many keys\n\n        err := VerifyAtLeastOneKeyIsPresent(objectType, keys )\n        if err != nil {\n                return nil, err\n        }\n\n\tcompoundKey, _ := stub.CreateCompositeKey(objectType, keys)\n\tfmt.Println(\"QueryObject: Compound Key : \", compoundKey)\n\n\tAvalbytes, err := stub.GetState(compoundKey)\n        if err != nil {\n                return nil, err\n        }\n\n        if Avalbytes == nil {\n                return nil,  fmt.Errorf(\"QueryObject: No Data Found for Compound Key : \", compoundKey)\n        }\n\n        // Perform Any additional processing of data\n        fmt.Println(\"fname() : Successful - Proceeding to fname\" )\n\n        err = fname(stub, Avalbytes, keys)\n        if err != nil {\n                fmt.Println(\"QueryLedger() : Cannot execute  : \", fname)\n                jsonResp := \"{\\\"fname() Error\\\":\\\" Cannot create Object for key \" + compoundKey + \"\\\"}\"\n                return Avalbytes, errors.New(jsonResp)\n        }\n\n\treturn Avalbytes, nil\n}\n\n////////////////////////////////////////////////////////////////////////////\n// Get a List of Rows based on query criteria from the OBC\n// The getList Function\n////////////////////////////////////////////////////////////////////////////\nfunc GetKeyList(stub shim.ChaincodeStubInterface, args []string) (shim.StateQueryIteratorInterface, error) {\n\n        // Define partial key to query within objects namespace (objectType)\n\tobjectType := args[0]\n\n        // Check how many keys\n\n        err := VerifyAtLeastOneKeyIsPresent(objectType, args[1:] )\n        if err != nil {\n                return nil, err\n        }\n\n        // Execute the Query\n        // This will execute a key range query on all keys starting with the compound key\n        resultsIterator, err := stub.GetStateByPartialCompositeKey(objectType, args[1:])\n        if err != nil {\n                return nil, err\n        }\n\n        defer resultsIterator.Close()\n\n        // Iterate through result set\n        var i int\n        for i = 0; resultsIterator.HasNext(); i++ {\n\n                // Retrieve the Key and Object\n                myCompositeKey, err := resultsIterator.Next()\n                if err != nil {\n                        return nil, err\n                }\n                fmt.Println(\"GetList() : my Value : \", myCompositeKey.Key)\n\t}\n        return resultsIterator, nil\n}\n\n///////////////////////////////////////////////////////////////////////////////////////////\n// GetQueryResultForQueryString executes the passed in query string.\n// Result set is built and returned as a byte array containing the JSON results.\n///////////////////////////////////////////////////////////////////////////////////////////\nfunc GetQueryResultForQueryString(stub shim.ChaincodeStubInterface, queryString string) ([]byte, error) {\n\n        fmt.Println(\"GetQueryResultForQueryString() : getQueryResultForQueryString queryString:\\n%s\\n\", queryString)\n\n        resultsIterator, err := stub.GetQueryResult(queryString)\n        if err != nil {\n                return nil, err\n        }\n        defer resultsIterator.Close()\n\n        // buffer is a JSON array containing QueryRecords\n        var buffer bytes.Buffer\n        buffer.WriteString(\"[\")\n\n        bArrayMemberAlreadyWritten := false\n        for resultsIterator.HasNext() {\n                queryResult, err := resultsIterator.Next()\n                if err != nil {\n                        return nil, err\n                }\n                // Add a comma before array members, suppress it for the first array member\n                if bArrayMemberAlreadyWritten == true {\n                        buffer.WriteString(\",\")\n                }\n                buffer.WriteString(\"{\\\"Key\\\":\")\n                buffer.WriteString(\"\\\"\")\n                buffer.WriteString(queryResult.Key)\n                buffer.WriteString(\"\\\"\")\n\n                buffer.WriteString(\", \\\"Record\\\":\")\n                // Record is a JSON object, so we write as-is\n                buffer.WriteString(string(queryResult.Value))\n                buffer.WriteString(\"}\")\n                bArrayMemberAlreadyWritten = true\n        }\n        buffer.WriteString(\"]\")\n\n        fmt.Println(\"GetQueryResultForQueryString(): getQueryResultForQueryString queryResult:\\n%s\\n\", buffer.String())\n\n        return buffer.Bytes(), nil\n}\n\n//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n// Retrieve a list of Objects from the Query\n// The function returns an iterator from which objects can be retrieved.\n//      defer rs.Close()\n//\n//      // Iterate through result set\n//      var i int\n//      for i = 0; rs.HasNext(); i++ {\n//\n//              // We can process whichever return value is of interest\n//              myKey , myKeyVal , err := rs.Next()\n//              if err != nil {\n//                      return shim.Success(nil)\n//              }\n//              bob, _ := JSONtoUser(myKeyVal)\n//              fmt.Println(\"GetList() : my Value : \", bob)\n//      }\n//\n// eg: Args\":[\"fetchlist\", \"PARTY\",\"CHK\"]}\n// fetchList is the function that calls getList : ObjectType = \"Party\" and key is \"CHK\"\n//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\nfunc GetList(stub shim.ChaincodeStubInterface, objectType string, keys []string) (shim.StateQueryIteratorInterface , error) {\n\n\t// Check how many keys\n\n\terr := VerifyAtLeastOneKeyIsPresent(objectType, keys )\n        if err != nil {\n                return nil, err\n        }\n\n\t// Get Result set\n        resultIter, err := stub.GetStateByPartialCompositeKey(objectType, keys)\n        fmt.Println(\"GetList(): Retrieving Objects into an array\")\n        if err != nil {\n                return nil, err\n        }\n\n\t// Return iterator for result set\n\t// Use code above to retrieve objects\n        return resultIter, nil\n}\n\n////////////////////////////////////////////////////////////////////////////\n// This function verifies if the number of key provided is at least 1 and\n// < the the max keys defined for the Object\n////////////////////////////////////////////////////////////////////////////\n\nfunc VerifyAtLeastOneKeyIsPresent(objectType string, args []string) error {\n\n        // Check how many keys\n        nKeys := GetNumberOfKeys(objectType)\n        nCol := len(args)\n\tif nCol == 1 {\n\t\treturn nil\n\t}\n\n        if nCol < 1 {\n\t\terror_str :=  fmt.Sprintf(\"VerifyAtLeastOneKeyIsPresent() Failed: Atleast 1 Key must is needed :  nKeys : %s, nCol : %s \", nKeys, nCol)\n                fmt.Println(error_str)\n                return errors.New(error_str)\n        }\n\n        return nil\n}\n"
  },
  {
    "path": "art/scripts/CloseOpenAuction",
    "content": "peer chaincode invoke -l golang -o 127.0.0.1:7050 -n mycc -c '{\"Args\": [\"iCloseOpenAuctions\", \"2016\", \"CLAUC\", \"2017-01-23 13:53:00.3 +0000 UTC\"]}'\n"
  },
  {
    "path": "art/scripts/DeployAuction",
    "content": " peer chaincode deploy -n mycc -p github.com/hyperledger/fabric/auction/art/artchaincode -c '{\"Args\":[\"init\", \"A\", \"200\",\"B\", \"200\"]}'\n"
  },
  {
    "path": "art/scripts/InitAuc",
    "content": "peer chaincode install -C testchainid -n mycc -p github.com/hyperledger/fabric/auction/art/artchaincode -c '{\"Args\":[\"init\"]}' -v 1.0\n"
  },
  {
    "path": "art/scripts/InstAuc",
    "content": "peer chaincode instantiate -C testchainid -n mycc -p github.com/hyperledger/fabric/auction/art/artchaincode -c '{\"Args\":[\"init\"]}' -v 1.0\n"
  },
  {
    "path": "art/scripts/OpenAuctionRequestForBids",
    "content": "peer chaincode invoke -l golang -o 127.0.0.1:7050 -n mycc -c '{\"Args\":[\"iOpenAuctionForBids\", \"1111\", \"OPENAUC\", \"10\", \"2017-02-13 09:18:00\"]}'\n#peer chaincode invoke -l golang -o 127.0.0.1:7050 -n mycc -c '{\"Args\":[\"iOpenAuctionForBids\", \"1112\", \"OPENAUC\", \"10\", \"2017-02-13 09:18:00\"]}'\n"
  },
  {
    "path": "art/scripts/PostAuctionRequest",
    "content": "peer chaincode invoke -l golang -o 127.0.0.1:7050 -n mycc -c '{\"Args\":[\"iPostAuctionRequest\", \"1111\", \"AUCREQ\", \"1000\", \"200\", \"100\", \"04012016\", \"1200\", \"1800\", \"INIT\", \"2017-02-13 09:05:00\",\"2017-02-13 09:05:00\", \"2017-02-13 09:10:00\"]}'\npeer chaincode invoke -l golang -o 127.0.0.1:7050 -n mycc -c '{\"Args\":[\"iPostAuctionRequest\", \"1112\", \"AUCREQ\", \"1100\", \"200\", \"300\", \"04012016\", \"1200\", \"1800\", \"INIT\", \"2017-02-13 09:05:00\",\"2017-02-13 09:05:00\", \"2017-02-13 09:10:00\"]}'\n"
  },
  {
    "path": "art/scripts/PostItems",
    "content": " peer chaincode invoke -o 127.0.0.1:7050 -n mycc -c '{\"Args\":[\"iPostItem\", \"1000\", \"ARTINV\", \"Shadows by Asppen\", \"Asppen Messer\", \"20140202\", \"Original\", \"landscape\", \"Canvas\", \"15 x 15 in\", \"art1.png\",\"600\", \"100\", \"2017-01-23 14:04:05\"]}'\nsleep 5\n peer chaincode invoke -o 127.0.0.1:7050 -n mycc -c '{\"Args\":[\"iPostItem\", \"1100\", \"ARTINV\", \"modern Wall Painting\", \"Scott Palmer\", \"20140202\", \"Reprint\", \"landscape\", \"Acrylic\", \"10 x 10 in\", \"art2.png\",\"2600\", \"300\", \"2017-01-23 14:04:05\"]}'\nsleep 5\n peer chaincode invoke -o 127.0.0.1:7050 -n mycc -c '{\"Args\":[\"iPostItem\", \"1200\", \"ARTINV\", \"Splash of Color\", \"Jennifer Drew\", \"20160115\", \"Reprint\", \"modern\", \"Water Color\", \"15 x 15 in\", \"art3.png\",\"1600\", \"100\", \"2017-01-23 14:04:05\"]}'\nsleep 5\n peer chaincode invoke -o 127.0.0.1:7050 -n mycc -c '{\"Args\":[\"iPostItem\", \"1300\", \"ARTINV\", \"Female Water Color\", \"David Crest\", \"19900115\", \"Original\", \"modern\", \"Water Color\", \"12 x 17 in\", \"art4.png\",\"9600\", \"100\", \"2017-01-23 14:04:05\"]}'\nsleep 5\n peer chaincode invoke -o 127.0.0.1:7050 -n mycc -c '{\"Args\":[\"iPostItem\", \"1400\", \"ARTINV\", \"Nature\", \"James Thomas\", \"19900115\", \"Original\", \"modern\", \"Water Color\", \"12 x 17 in\", \"item-001.jpg\",\"1800\", \"100\", \"2017-01-23 14:04:05\"]}'\nsleep 5\n peer chaincode invoke -o 127.0.0.1:7050 -n mycc -c '{\"Args\":[\"iPostItem\", \"1500\", \"ARTINV\", \"Ladys Hair\", \"James Thomas\", \"19900115\", \"Original\", \"landscape\", \"Acrylic\", \"12 x 17 in\", \"item-002.jpg\",\"1200\", \"300\", \"2017-01-23 14:04:05\"]}'\nsleep 5\n peer chaincode invoke -o 127.0.0.1:7050 -n mycc -c '{\"Args\":[\"iPostItem\", \"1600\", \"ARTINV\", \"Flowers\", \"James Thomas\", \"19900115\", \"Original\", \"modern\", \"Acrylic\", \"12 x 17 in\", \"item-003.jpg\",\"1000\", \"300\", \"2017-01-23 14:04:05\"]}'\nsleep 5\n peer chaincode invoke -o 127.0.0.1:7050 -n mycc -c '{\"Args\":[\"iPostItem\", \"1700\", \"ARTINV\", \"Women at work\", \"James Thomas\", \"19900115\", \"Original\", \"modern\", \"Acrylic\", \"12 x 17 in\", \"item-004.jpg\",\"1500\", \"400\", \"2017-01-23 14:04:05\"]}'\nsleep 5\n peer chaincode invoke -o 127.0.0.1:7050 -n mycc -c '{\"Args\":[\"iPostItem\", \"1800\", \"ARTINV\", \"People\", \"James Thomas\", \"19900115\", \"Original\", \"modern\", \"Acrylic\", \"12 x 17 in\", \"people.gif\",\"900\", \"400\", \"2017-01-23 14:04:05\"]}'\nsleep 5\n peer chaincode invoke -o 127.0.0.1:7050 -n mycc -c '{\"Args\":[\"iPostItem\", \"1900\", \"ARTINV\", \"Mad fb\", \"James Thomas\", \"19900115\", \"Original\", \"modern\", \"Acrylic\", \"12 x 17 in\", \"mad-fb.jpg\",\"1100\", \"500\", \"2017-01-23 14:04:05\"]}'\nsleep 5\n"
  },
  {
    "path": "art/scripts/PostUsers",
    "content": " peer chaincode invoke -o 127.0.0.1:7050 -n mycc -c  '{\"Args\":[\"iPostUser\",\"100\", \"USER\", \"Ashley Hart\", \"TRD\",  \"Morrisville Parkway, #216, Morrisville, NC 27560\", \"9198063535\", \"ashley@itpeople.com\", \"SUNTRUST\", \"0001732345\", \"0234678\", \"2017-01-02 15:04:05\"]}'\nsleep 5\n peer chaincode invoke -o 127.0.0.1:7050 -n mycc -c  '{\"Args\":[\"iPostUser\",\"200\", \"USER\", \"Sotheby\", \"AH\",  \"One Picadally Circus , #216, London, UK \", \"9198063535\", \"admin@sotheby.com\", \"Standard Chartered\", \"0001732345\", \"0234678\", \"2017-01-02 15:04:05\"]}'\nsleep 5\n peer chaincode invoke -o 127.0.0.1:7050 -n mycc -c  '{\"Args\":[\"iPostUser\",\"300\", \"USER\", \"Barry Smith\", \"TRD\",  \"155 Regency Parkway, #111, Cary, 27518 \", \"9198063535\", \"barry@us.ibm.com\", \"RBC Centura\", \"0001732345\", \"0234678\", \"2017-01-02 15:04:05\"]}'\nsleep 5\n peer chaincode invoke -o 127.0.0.1:7050 -n mycc -c  '{\"Args\":[\"iPostUser\",\"400\", \"USER\", \"Cindy Patterson\", \"TRD\",  \"155 Sunset Blvd, Beverly Hills, CA, USA \", \"9058063535\", \"cpatterson@hotmail.com\", \"RBC Centura\", \"0001732345\", \"0234678\", \"2017-01-02 15:04:05\"]}'\nsleep 5\n peer chaincode invoke -o 127.0.0.1:7050 -n mycc -c  '{\"Args\":[\"iPostUser\",\"500\", \"USER\", \"Tamara Haskins\", \"TRD\",  \"155 Sunset Blvd, Beverly Hills, CA, USA \", \"9058063535\", \"tamara@yahoo.com\", \"RBC Centura\", \"0001732345\", \"0234678\", \"2017-01-02 15:04:05\"]}'\nsleep 5\n peer chaincode invoke -o 127.0.0.1:7050 -n mycc -c  '{\"Args\":[\"iPostUser\",\"600\", \"USER\", \"NY Life\", \"INS\",  \"155 Broadway, New York, NY, USA \", \"9058063535\", \"barry@nyl.com\", \"RBC Centura\", \"0001732345\", \"0234678\", \"2017-01-02 15:04:05\"]}'\nsleep 5\n peer chaincode invoke -o 127.0.0.1:7050 -n mycc -c  '{\"Args\":[\"iPostUser\",\"700\", \"USER\", \"J B Hunt\", \"SHP\",  \"One Johnny Blvd, Rogers, AR, USA \", \"9058063535\", \"jess@jbhunt.com\", \"RBC Centura\", \"0001732345\", \"0234678\", \"2017-01-02 15:04:05\"]}'\nsleep 5\n peer chaincode invoke -o 127.0.0.1:7050 -n mycc -c  '{\"Args\":[\"iPostUser\",\"800\", \"USER\", \"R&R Trading\", \"AH\",  \"155 Sunset Blvd, Beverly Hills, CA, USA \", \"9058063535\", \"larry@rr.com\", \"RBC Centura\", \"0001732345\", \"0234678\", \"2017-01-02 15:04:05\"]}'\n"
  },
  {
    "path": "art/scripts/Script4Demo.sh",
    "content": "#!/bin/bash\n\necho '################# STARTED POST USERS #################'\npeer chaincode deploy -l golang -n mycc -c '{\"Function\": \"init\", \"Args\":[\"INITIALIZE\"]}'\nsleep 1\npeer chaincode invoke -l golang -n mycc -c '{\"Function\": \"PostUser\", \"Args\":[\"200\", \"USER\", \"Heritage Auctions\", \"AH\",  \"3500 Maple Avenue, 17th Floor Dallas, Texas 75219 \", \"214-528-3500\", \"admin@ha.com\", \"Standard Chartered\", \"0001732345\", \"0234678\"]}'\nsleep 1\npeer chaincode invoke -l golang -n mycc -c '{\"Function\": \"PostUser\", \"Args\":[\"300\", \"USER\", \"Barry Smith\", \"TRD\",  \"155 Regency Parkway, #111, Cary, 27518 \", \"919-806-3535\", \"barrys@us.ibm.com\", \"RBC Centura\", \"0001732345\", \"1634678\"]}'\nsleep 1\npeer chaincode invoke -l golang -n mycc -c '{\"Function\": \"PostUser\", \"Args\":[\"400\", \"USER\", \"Cindy Patterson\", \"TRD\",  \"155 Sunset Blvd, Beverly Hills, CA, USA \", \"905-806-3535\", \"cpatterson@hotmail.com\", \"RBC Centura\", \"0001732345\", \"0234678\"]}'\nsleep 1\npeer chaincode invoke -l golang -n mycc -c '{\"Function\": \"PostUser\", \"Args\":[\"500\", \"USER\", \"Tamara Haskins\", \"TRD\",  \"155 Sunset Blvd, Beverly Hills, CA, USA \", \"9058063535\", \"tamara@yahoo.com\", \"RBC Centura\", \"0001732345\", \"5235678\"]}'\nsleep 1\npeer chaincode invoke -l golang -n mycc -c '{\"Function\": \"PostUser\", \"Args\":[\"600\", \"USER\", \"Jacob\", \"TRD\",  \"155 Broadway, New York, NY, USA \", \"118-806-3535\", \"jacob@gmail.com\", \"RBC Centura\", \"0001732345\", \"0234678\"]}'\nsleep 1\npeer chaincode invoke -l golang -n mycc -c '{\"Function\": \"PostUser\", \"Args\":[\"700\", \"USER\", \"Suntrust\", \"BNK\",  \"155 Sunset Blvd, Beverly Hills, CA, USA \", \"9058063535\", \"admin@suntrust.com\", \"Suntrust\", \"0001732345\", \"2023678\"]}'\nsleep 1\npeer chaincode invoke -l golang -n mycc -c '{\"Function\": \"PostUser\", \"Args\":[\"800\", \"USER\", \"J B Hunt\", \"SHP\",  \"One Johnny Blvd, Rogers, AR, USA \", \"9058063535\", \"jess@jbhunt.com\", \"RBC Centura\", \"0001732345\", \"1023687\"]}'\nsleep 1\npeer chaincode invoke -l golang -n mycc -c '{\"Function\": \"PostUser\", \"Args\":[\"900\", \"USER\", \"Metlife\", \"MET\",  \"201 MetLife Way Cary, NC 27513\", \"215-806-3535\", \"admin@metlife.com\", \"Standard Chartered\", \"3001745345\", \"9734678\"]}'\nsleep 1\necho '################# COMPLETED POST USERS #################'\necho '################# STARTED POST ITEMS #################'\npeer chaincode invoke -l golang -n mycc -c '{\"Function\": \"PostItem\", \"Args\":[\"1100\", \"ARTINV\", \"Bowl Of Grapes\", \"jacques Linard\", \"01-08-2008\", \"Reprint\", \"landscape\", \"Canvas\", \"45 x 45 in\", \"item-004.jpg\",\"8500\", \"300\"]}'\nsleep 3\npeer chaincode invoke -l golang -n mycc -c '{\"Function\": \"PostItem\", \"Args\":[\"1200\", \"ARTINV\", \"Modern Wall Painting\", \"Scott Palmer\", \"02-02-2010\", \"Reprint\", \"modern\", \"Acrylic\", \"10 x 10 in\", \"art1.png\",\"6000\", \"300\"]}'\nsleep 3\npeer chaincode invoke -l golang -n mycc -c '{\"Function\": \"PostItem\", \"Args\":[\"1300\", \"ARTINV\", \"Splash of Color\", \"Jennifer Drew\", \"06-05-2016\", \"Reprint\", \"modern\", \"Water Color\", \"15 x 15 in\", \"art2.png\",\"8000\", \"300\"]}'\nsleep 3\npeer chaincode invoke -l golang -n mycc -c '{\"Function\": \"PostItem\", \"Args\":[\"1400\", \"ARTINV\", \"Female Water Color\", \"David Crest\", \"01-15-1990\", \"Reprint\", \"modern\", \"Water Color\", \"15 x 15 in\", \"art3.png\",\"5000\", \"300\"]}'\nsleep 3\npeer chaincode invoke -l golang -n mycc -c '{\"Function\": \"PostItem\", \"Args\":[\"1500\", \"ARTINV\", \"Mother and Child\", \"Hugues Merle\", \"02-08-1600\", \"Original\", \"landscape\", \"Canvas\", \"17 x 17 in\", \"item-003.jpg\",\"4000\", \"300\"]}'\nsleep 3\necho '################# COMPLETED POST ITEMS #################'\n"
  },
  {
    "path": "art/scripts/SubmitBids",
    "content": "peer chaincode invoke -l golang -o 127.0.0.1:7050 -n mycc -c '{\"Args\":[\"iPostBid\", \"1111\", \"BID\", \"1\", \"1000\", \"300\", \"1200\", \"2017-02-13 09:19:01\"]}'\nsleep 5\npeer chaincode invoke -l golang -o 127.0.0.1:7050 -n mycc -c '{\"Args\":[\"iPostBid\", \"1111\", \"BID\", \"2\", \"1000\", \"400\", \"3000\", \"2017-02-13 09:19:02\"]}'\nsleep 5\npeer chaincode invoke -l golang -o 127.0.0.1:7050 -n mycc -c '{\"Args\":[\"iPostBid\", \"1111\", \"BID\", \"3\", \"1000\", \"400\", \"6000\", \"2017-02-13 09:19:03\"]}'\nsleep 5\npeer chaincode invoke -l golang -o 127.0.0.1:7050 -n mycc -c '{\"Args\":[\"iPostBid\", \"1111\", \"BID\", \"4\", \"1000\", \"500\", \"7000\", \"2017-02-13 09:19:04\"]}'\nsleep 5\npeer chaincode invoke -l golang -o 127.0.0.1:7050 -n mycc -c '{\"Args\":[\"iPostBid\", \"1111\", \"BID\", \"5\", \"1000\", \"400\", \"8000\", \"2017-02-13 09:19:05\"]}'\nsleep 5\npeer chaincode invoke -l golang -o 127.0.0.1:7050 -n mycc -c '{\"Args\":[\"iPostBid\", \"1111\", \"BID\", \"6\", \"1000\", \"600\", \"8200\", \"2017-02-13 09:19:06\"]}'\nsleep 5\npeer chaincode invoke -l golang -o 127.0.0.1:7050 -n mycc -c '{\"Args\":[\"iPostBid\", \"1111\", \"BID\", \"7\", \"1000\", \"700\", \"8400\", \"2017-02-13 09:19:07\"]}'\nsleep 5\npeer chaincode invoke -l golang -o 127.0.0.1:7050 -n mycc -c '{\"Args\":[\"iPostBid\", \"1111\", \"BID\", \"8\", \"1000\", \"300\", \"8900\", \"2017-02-13 09:19:08\"]}'\nsleep 5\npeer chaincode invoke -l golang -o 127.0.0.1:7050 -n mycc -c '{\"Args\":[\"iPostBid\", \"1111\", \"BID\", \"9\", \"1000\", \"400\", \"9000\", \"2017-02-13 09:19:09\"]}'\nsleep 5\npeer chaincode invoke -l golang -o 127.0.0.1:7050 -n mycc -c '{\"Args\":[\"iPostBid\", \"1111\", \"BID\", \"10\", \"1000\", \"500\", \"12000\", \"2017-02-12 09:20:00\"]}'\nsleep 5\n\n\n"
  },
  {
    "path": "art/scripts/SubmitQueries",
    "content": "peer chaincode query -l golang -n mycc -c '{\"Args\": [\"qGetUser\", \"100\"]}'\npeer chaincode query -l golang -n mycc -c '{\"Args\": [\"qGetUser\", \"200\"]}'\npeer chaincode query -l golang -n mycc -c '{\"Args\": [\"qGetUser\", \"300\"]}'\npeer chaincode query -l golang -n mycc -c '{\"Args\": [\"qGetUser\", \"400\"]}'\npeer chaincode query -l golang -n mycc -c '{\"Args\": [\"qGetUser\", \"500\"]}'\npeer chaincode query -l golang -n mycc -c '{\"Args\": [\"qGetAuctionRequest\", \"1111\"]}'\npeer chaincode query -l golang -n mycc -c '{\"Args\": [\"qGetListOfBids\", \"1111\"]}'\npeer chaincode query -l golang -n mycc -c '{\"Args\": [\"qGetLastBid\", \"1111\"]}'\npeer chaincode query -l golang -n mycc -c '{\"Args\": [\"qGetHighestBid\", \"1111\"]}'\npeer chaincode query -l golang -n mycc -c '{\"Args\": [\"qGetItem\", \"1000\"]}'\npeer chaincode query -l golang -n mycc -c '{\"Args\": [\"qGetAuctionRequest\", \"1111\"]}'\npeer chaincode query -l golang -n mycc -c '{\"Args\": [\"qGetItemLog\", \"1000\"]}'\npeer chaincode query -l golang -n mycc -c '{\"Args\": [\"qGetAuctionRequest\", \"1111\"]}'\npeer chaincode query -l golang -n mycc -c '{\"Args\": [\"qGetListOfInitAucs\", \"2016\"]}'\npeer chaincode query -l golang -n mycc -c '{\"Args\": [\"qGetListOfOpenAucs\", \"2016\"]}'\n"
  },
  {
    "path": "art/scripts/TransferItem",
    "content": "# Please update data with correct item id, owner and key\npeer chaincode invoke -l golang -o 127.0.0.1:7050 -n mycc -c '{\"Function\": \"iTransferItem\", \"Args\": [\"1000\", \"500\", \"Ub0GsO1F8wsCv2LCCMudITn2Z61ZOeOH+kXs9ZsbMv0=\", \"300\", \"XFER\",\"2017-01-24 11:00:00\"]}'\n\n"
  },
  {
    "path": "art/scripts/ValidateItemOwnerShip",
    "content": "# Update the itemid, ownerid and key as appropriate\npeer chaincode query -l golang -o 127.0.0.1:7050 -n mycc -c '{\"Function\": \"qValidateItemOwnership\", \"Args\": [\"1000\", \"300\", \"s2knz/slWPjhPFdHnZTk2hZ863TPXqn/L1AYR8DyYEo=\"]}'\npeer chaincode query -l golang -o 127.0.0.1:7050 -n mycc -c '{\"Function\": \"qValidateItemOwnership\", \"Args\": [\"1900\", \"500\", \"Ac0o41Lg19fFcrT02Bo4gI1NM0c3QDtVmZM+ODqYsxY=\"]}'\n"
  },
  {
    "path": "art/scripts/auction_e2e_script.sh",
    "content": "#!/bin/bash\nORDERER_IP=orderer.example.com:7050\nORDERER_CA=$GOPATH/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem\nCHANNEL_NAME=mychannel\nCHAINCODE_NAME=mycc\n\n## Install\npeer chaincode install -n $CHAINCODE_NAME -v 1 -p github.com/hyperledger/fabric/examples/chaincode/go/auction\n##Instantiate\npeer chaincode instantiate -o $ORDERER_IP --tls --cafile $ORDERER_CA -C $CHANNEL_NAME -n $CHAINCODE_NAME -v 1 -c '{\"Args\":[\"init\"]}' -P \"OR ('Org1MSP.peer','Org2MSP.peer')\"\n\n##Post Users - invoke\npeer chaincode invoke -o $ORDERER_IP --tls --cafile $ORDERER_CA -C $CHANNEL_NAME -n $CHAINCODE_NAME -c '{\"Args\":[\"iPostUser\",\"100\", \"USER\", \"Ashley Hart\", \"TRD\",  \"Morrisville Parkway, #216, Morrisville, NC 27560\", \"9198063535\", \"ashley@itpeople.com\", \"SUNTRUST\", \"0001732345\", \"0234678\", \"2017-01-02 15:04:05\"]}'\npeer chaincode invoke -o $ORDERER_IP --tls --cafile $ORDERER_CA -C $CHANNEL_NAME -n $CHAINCODE_NAME -c '{\"Args\":[\"iPostUser\",\"200\", \"USER\", \"Sotheby\", \"AH\",  \"One Picadally Circus , #216, London, UK \", \"9198063535\", \"admin@sotheby.com\", \"Standard Chartered\", \"0001732345\", \"0234678\", \"2017-01-02 15:04:05\"]}'\n\n##Get Users - query\npeer chaincode query -C $CHANNEL_NAME -n $CHAINCODE_NAME -c \"{\\\"Args\\\": [\\\"qGetUser\\\", \\\"100\\\"]}\"\npeer chaincode query -C $CHANNEL_NAME -n $CHAINCODE_NAME -c \"{\\\"Args\\\": [\\\"qGetUser\\\", \\\"200\\\"]}\"\n\n\n##Post Items - invoke\npeer chaincode invoke -o $ORDERER_IP --tls --cafile $ORDERER_CA -C $CHANNEL_NAME -n $CHAINCODE_NAME -c '{\"Args\":[\"iPostItem\", \"100\", \"ARTINV\", \"Shadows by Asppen\", \"Asppen Messer\", \"20140202\", \"Original\", \"landscape\", \"Canvas\", \"15 x 15 in\", \"art1.png\",\"600\", \"100\", \"2017-01-23 14:04:05\"]}'\npeer chaincode invoke -o $ORDERER_IP --tls --cafile $ORDERER_CA -C $CHANNEL_NAME -n $CHAINCODE_NAME -c '{\"Args\":[\"iPostItem\", \"200\", \"ARTINV\", \"modern Wall Painting\", \"Scott Palmer\", \"20140202\", \"Reprint\", \"landscape\", \"Acrylic\", \"10 x 10 in\", \"art2.png\",\"2600\", \"200\", \"2017-01-23 14:04:05\"]}'\n\n##Get Items - query\npeer chaincode query -C $CHANNEL_NAME -n $CHAINCODE_NAME -c \"{\\\"Args\\\": [\\\"qGetItem\\\", \\\"100\\\"]}\"\npeer chaincode query -C $CHANNEL_NAME -n $CHAINCODE_NAME -c \"{\\\"Args\\\": [\\\"qGetItem\\\", \\\"200\\\"]}\"\n\n\n## postAuction\npeer chaincode invoke -o $ORDERER_IP --tls --cafile $ORDERER_CA -C $CHANNEL_NAME -n $CHAINCODE_NAME -c \"{\\\"Args\\\":[\\\"iPostAuctionRequest\\\", \\\"1000\\\", \\\"AUCREQ\\\", \\\"100\\\", \\\"200\\\", \\\"100\\\", \\\"04012016\\\", \\\"1000\\\", \\\"1000\\\", \\\"INIT\\\", \\\"2017-02-13 09:05:00\\\", \\\"2017-02-13 09:05:00\\\", \\\"2017-02-13 09:10:00\\\"]}\"\n\n## openAuctionRequestForBids\npeer chaincode invoke -o $ORDERER_IP --tls --cafile $ORDERER_CA -C $CHANNEL_NAME -n $CHAINCODE_NAME -c \"{\\\"Args\\\":[\\\"iOpenAuctionForBids\\\", \\\"1000\\\", \\\"OPENAUC\\\", \\\"10\\\", \\\"2017-02-13 09:18:00\\\"]}\"\n\n\n## submitBids $ch $chain $(((RANDOM % 3))) $auctionindex $bidNumber $userid $biduserid $bidPrice\npeer chaincode invoke -o $ORDERER_IP --tls --cafile $ORDERER_CA -C $CHANNEL_NAME -n $CHAINCODE_NAME -c \"{\\\"Args\\\":[\\\"iPostBid\\\", \\\"1000\\\", \\\"BID\\\", \\\"1000\\\", \\\"100\\\", \\\"100\\\", \\\"5000\\\", \\\"2017-02-13 09:19:01\\\"]}\"\n# peer chaincode invoke -o $ORDERER_IP --tls --cafile $ORDERER_CA -C $CHANNEL_NAME -n $CHAINCODE_NAME -c \"{\\\"Args\\\":[\\\"iPostBid\\\", \\\"1000\\\", \\\"BID\\\", \\\"1001\\\", \\\"200\\\", \\\"100\\\", \\\"5001\\\", \\\"2017-02-13 09:19:01\\\"]}\"\n\n##closeAuction\npeer chaincode invoke -o $ORDERER_IP --tls --cafile $ORDERER_CA -C $CHANNEL_NAME -n $CHAINCODE_NAME -c '{\"Args\": [\"iCloseOpenAuctions\", \"2016\", \"CLAUC\", \"2017-01-23 13:53:00.3 +0000 UTC\"]}'\n\n#Query for the item\npeer chaincode query -C $CHANNEL_NAME -n $CHAINCODE_NAME -c \"{\\\"Args\\\": [\\\"qGetItem\\\", \\\"1000\\\"]}\"\n\n\nAES_KEY=\"/UucdM++9gqy3X7TztFTbPbSiEsbj4WudUi2CuSZ4OU=\"\n\n## transferItem\npeer chaincode invoke -o $ORDERER_IP --tls --cafile $ORDERER_CA -C $CHANNEL_NAME -n $CHAINCODE_NAME -c \"{\\\"Args\\\": [\\\"iTransferItem\\\", \\\"100\\\", \\\"100\\\", $AES_KEY, \\\"200\\\", \\\"XFER\\\",\\\"2017-01-24 11:00:00\\\"]}\"\n"
  },
  {
    "path": "art/scripts/downloadImages.sh",
    "content": "#!/bin/bash\n\nwget -q https://raw.githubusercontent.com/ITPeople-Blockchain/auction/v0.6/art/artchaincode/art1.png\nwget -q https://raw.githubusercontent.com/ITPeople-Blockchain/auction/v0.6/art/artchaincode/art1.png\nwget -q https://raw.githubusercontent.com/ITPeople-Blockchain/auction/v0.6/art/artchaincode/art1.png\nwget -q https://raw.githubusercontent.com/ITPeople-Blockchain/auction/v0.6/art/artchaincode/art1.png\nwget -q https://raw.githubusercontent.com/ITPeople-Blockchain/auction/v0.6/art/artchaincode/art1.png\nwget -q https://raw.githubusercontent.com/ITPeople-Blockchain/auction/v0.6/art/artchaincode/art1.png\nwget -q https://raw.githubusercontent.com/ITPeople-Blockchain/auction/v0.6/art/artchaincode/art1.png\n"
  },
  {
    "path": "art/scripts/env.sh",
    "content": "#!/bin/bash\n\nexport CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/msp/sampleconfig\n"
  },
  {
    "path": "art/scripts/getaucrequest",
    "content": "peer chaincode query -l golang -n mycc -c '{\"Args\": [\"qGetAuctionRequest\", \"1111\"]}'\npeer chaincode query -l golang -n mycc -c '{\"Args\": [\"qGetAuctionRequest\", \"1112\"]}'\n"
  },
  {
    "path": "art/scripts/getbids",
    "content": "peer chaincode query -l golang -o 127.0.0.1:7050 -n mycc -c '{\"Args\": [\"qGetListOfBids\", \"1111\"]}'\npeer chaincode query -l golang -o 127.0.0.1:7050 -n mycc -c '{\"Args\": [\"qGetLastBid\", \"1111\"]}'\npeer chaincode query -l golang -o 127.0.0.1:7050 -n mycc -c '{\"Args\": [\"qGetHighestBid\", \"1111\"]}'\n"
  },
  {
    "path": "art/scripts/getitem",
    "content": "peer chaincode query -l golang -o 127.0.0.1:7050 -n mycc -c '{\"Args\": [\"qGetItem\", \"1000\"]}'\n"
  },
  {
    "path": "art/scripts/getitemlog",
    "content": "peer chaincode query -l golang -n mycc -c '{\"Args\": [\"qGetItemLog\", \"1000\"]}'\n"
  },
  {
    "path": "art/scripts/getlistofaucs",
    "content": "peer chaincode query -l golang -o 127.0.0.1:7050 -n mycc -c '{\"Args\": [\"qGetListOfInitAucs\", \"2017\"]}'\npeer chaincode query -l golang -o 127.0.0.1:7050 -n mycc -c '{\"Args\": [\"qGetListOfOpenAucs\", \"2017\"]}'\n"
  },
  {
    "path": "art/scripts/getuser",
    "content": "peer chaincode query -l golang -o 127.0.0.1:7050 -n mycc -c '{\"Args\": [\"qGetUser\", \"100\"]}'\npeer chaincode query -l golang -o 127.0.0.1:7050 -n mycc -c '{\"Args\": [\"qGetUser\", \"200\"]}'\npeer chaincode query -l golang -o 127.0.0.1:7050 -n mycc -c '{\"Args\": [\"qGetUser\", \"300\"]}'\npeer chaincode query -l golang -o 127.0.0.1:7050 -n mycc -c '{\"Args\": [\"qGetUser\", \"400\"]}'\npeer chaincode query -l golang -o 127.0.0.1:7050 -n mycc -c '{\"Args\": [\"qGetUser\", \"500\"]}'\n"
  },
  {
    "path": "art/scripts/setup.sh",
    "content": "#!/bin/sh\n\nexport PEER=$GOPATH/src/github.com/hyperledger/build/bin/peer\n"
  },
  {
    "path": "docs/Datastructures.txt",
    "content": "Data Structures\n\n# User Object\n\nUserID, RecType, Name, UserType, Address, Phone, Email, Bank, AccountNo, RoutingNo \n\n        UserID    \n        RecType    // Type = USER\n        Name      \n        UserType   // Auction House (AH), Bank (BK), Buyer or Seller (TR), Shipper (SH), Appraiser (AP)\n        Address   \n        Phone     \n        Email     \n        Bank      \n        AccountNo \n        RoutingNo \n\n# Item Object\n\nItem ID, RecType, Description, Details,Date of Origin, Type (Original or Reprint), Subject Area, Media (Canvas or Acrylic ..), Dimensions, File name (Certificate or image), Price, Current OwnerID \n# The following attributes are inserted during processing after the image file name.\n\n        ItemID         // AN Item identifier\n        RecType        // ARTINV\n        ItemDesc       // Description of the Item\n        ItemDetail     // Could included details such as who created the Art work if item is a Painting\n        ItemDate       // Date of Origin\n        ItemType       // Original or Reprint\n        ItemSubject    // Subject Area - Landscape, Modern, Potrait\n        ItemMedia      // Media like Canvas, Acrylic, Water Color\n        ItemSize       // Dimensions\n        ItemPicFN      // The file name of the picture or certificate\n        ItemImage      // This has to be generated AES encrypted using the file name\n        AES_Key        // This is generated by the AES Algorithms\n        ItemImageType  // should be used to regenerate the appropriate image type\n        ItemBasePrice  // Reserve Price at Auction must be greater than this price\n        CurrentOwnerID // This is validated for a user registered record\n\n\n# Auction Request\n\n        AuctionID      \n        RecType         // AUCREQ\n        ItemID         \n        AuctionHouseID  // ID of the Auction House managing the auction\n        SellerID        // ID Of Seller - to verified against the Item CurrentOwnerId\n        RequestDate     // Date on which Auction Request was filed\n        ReservePrice    // reserve price > previous purchase price\n        Status          // INIT, OPEN, CLOSED  (Updated by Open Auction)\n        OpenDate        // Date on which auction will occur (Updated by Open Auction)\n        CloseDate       // Date and time when Auction will close  (Updated by Open Auction)\n\n# BID\n        AuctionID \n        RecType    // BID\n        BidNo      // In future - chaincode generated\n        ItemID     // ID of Item (In future - one auction many items )\n        BuyerID    // ID Of Buyer - to be verified against the Item CurrentOwnerId\n        BidPrice   // BidPrice > Previous Bid\n        BidTime    // Time the bid was received\n\n# Transaction\n\n        AuctionID   \n        RecType      // POSTTRAN\n        ItemID       // ID of item that got sold\n        TransType    // Sale, Buy, Commission\n        UserId       // Buyer ID\n        TransDate    // Date of Settlement (Buyer or Seller)\n        HammerTime   // Time of hammer strike - SOLD\n        HammerPrice  // Total Settlement price\n        Details      // Details about the Transaction\n\n\n"
  },
  {
    "path": "docs/index.md",
    "content": "[![Documentation Status](https://readthedocs.org/projects/itpeople-blockchain-auction/badge/?version=latest)](http://itpeople-blockchain-auction.readthedocs.io/en/latest/?badge=latest)\r\n\r\n#Art Auction Blockchain Application\r\nCredits: Ratnakar Asara, Nishi Nidamarty, Ramesh Thoomu, Adam Gordon and Mohan Venkataraman\r\n\r\n**Disclaimer:** The images used in this sample PoC application have been downloaded from publicly available images on the internet, and the copyright belongs to the respective owners. The usage here is strictly for non-commercial purposes as sample data. We recommend that users create their own sample data as appropriate. All names, addresses and accounts numbers used in the sample data are fictitous. The information provided in this README.md is subject to change.\r\n\r\nAuction Chaincode is migrated to fabric v1.0 and these changes being tested on **fabric commit#** 5b59e0652f9edf5bd12a6ff7fd2e9991495190fe\r\n\r\n##Introduction\r\n\r\nThis Hyperledger/Fabric is an implementation of blockchain technology, leveraging familiar and proven technologies. It is a modular architecture allowing pluggable implementations of various function. It features powerful container technology to host any mainstream language for smart contracts development. Chaincode (smart contracts) or blockchain applications run on the fabric. Chaincode is written in Go language \r\n\r\nThe original intention of this application was to understand how to write a Go application on the Hyperledger/Fabric. This initial version was written to understand the different chaincode api's, the boundary that separates what goes into the blockchain and what lives within the enterprise application, usage of database features, error management etc. <br> </br>\r\n\r\n<img src=\"docs/images/auction_chain.png\" width=\"700\">\r\n## Application Description\r\n\r\nThis application deals with auctioning ART on the block chain. The blockchain makes sense here as there are many different stakeholders and can leverage the benefits of the \"Network Effect\". This application deals with the following stake holders:\r\n* Buyers and Sellers or Traders (TRD)\r\n* Banks (BNK)\r\n* Insurance Companies (INS)\r\n* Shipping and Forwarding (SHP)\r\n* Auction Houses (AH)\r\n* Art Dealers (DEL)\r\n* Artists (ART)\r\n\r\nThe typical business process is shown below\r\n![Business Process](docs/images/art_process.png)\r\n\r\n###Registering Stakeholder Accounts\r\n\r\nArtists, Traders, Dealers own **Assets** (Items). Auction Houses, Banks, Insurance Companies and Service Providers play a role in the auction process. To conduct business on the block chain, the stakeholder has to open an account on the block chain. In the production world, prior to opening an account, all of the stake-holder details may be authenticated by another blockchain like an IDaaS (Identity-as-a-Service). There are various stake holders as listed above, each with a different interest.\r\n\r\n###Registering Assets or Items\r\n\r\nThe Seller (Trader) who owns **Assets** must register the asset on the block chain in order to conduct business. When an **Asset** is submitted for registration, the chaincode does the following:\r\n   * Checks if the owner has a registered account\r\n   * Converts any presented \"Certificate of Authenticity\" or a credibly issued image to a byte stream, generates a key, encrypts the byte stream using the key and stores the image on the BC \r\n   * Provides the key to the **owner** for safe keeping and future reference\r\n   * Makes entries into the Item History so that the lifecycle of the Asset can be reviewed at any time\r\n\r\n###Making a Request to Auction an Asset\r\n\r\nWhen the owner of an Asset sees an opportunity to make money, they would like to auction the Asset. They engage an Auction House and make a **request to auction** the Asset. The request always specifies a **\"Reserve Price\"**. Sometimes, the owner may additionally specify a **\"Buy It Now\"** price as well. When the request is made, the item, owner and the auction house are all validated. (The chaincode simply validates that they are all registered on the BC).\r\n\r\nThe Auction House will most likely, behind the scene, get the Asset authenticated and determine the valuation before deciding to accept the item. One of the ways by which they could do some preliminary authentication is to request the **seller** to enter his **private key**, account-id and the registered item number into the client application. While the item number and account identifier is a straight validation, the key will be used to decrypt and retrieve the stored \"certificate of authenticity or image\". The state of the Auction is set to **INIT** at this point, until the Auction House is ready to **OPEN** the Asset for bids.\r\n\r\n###Opening the Auction for Bids\r\n\r\nThe Auction House will choose a time frame to place the item on auction and **OPEN** it up for accepting bids from potential Buyers. They may, if applicable, advertise the **BuyItNow** price.\r\n\r\n### \"Buy It Now\" and Accepting Bids\r\n\r\nDuring the window of the auction, potential buyers can place bids. If a Buyer wishes to exercise the \"Buy It Now\", they can buy the item right away provided there is no bid higher than the \"BuyItNow\" price.\r\n\r\nBids are accepted from buyers if\r\n   * The Bids have are equal or greater than the **Reserve Price\"**\r\n   * The auction is still **OPEN**\r\n   * The Buyer has a registered account\r\n\r\n### Buy It Now\r\n\r\nWhen a buyer chooses this option, the chain code does the following\r\n    * Validates the Buyer\r\n    * Checks if there are any bidders whose bid is higher than the **\"Buy It Now\"** price. If so, the offer is rejected\r\n    * If the **\"Buy It Now\"** price is applicable, it immediately **\"CLOSES\"** the auctions, creates a **transaction**\r\n    * It assigns the Asset to the new owner\r\n    * It also generates a new **Key**, re-encrypts the \"Certificate of Ownership or Image\", and provides the key to the new buyer\r\n    * The new price of the Asset is set to the **\"Buy It Now\"** price if not higher\r\n\r\n### Auction Expiry\r\n\r\nWhen the auction expires, the Auction House retrieves the highest bid and converts it to a **transaction** ( A transaction in the real world could mean creating insurance and shipping docs, collecting payments and commissions, issuing a new title or certificate to the new owner etc.), transfers ownership to the buyer and updates the price with the new **\"Hammer\"** price. It also generates a new **Key**, re-encrypts the \"Certificate of Ownership or Image\", and provides the key to the new buyer.\r\n\r\n### Transfer an Item to another User\r\n\r\nThe chain code supports this scenario, by allowing a **owner** of an Asset to transfer **\"ownership\"** to another person. The receiving person has to be registered on the block-chain. Currently the chain code does not execute any regulatory or compliance rules.\r\n\r\n### Validating Asset Ownership\r\n\r\nThe chain code supports this. In order to accomplish this, it does preliminary authentication by requesting the **seller** to enter his **private key**, account-id and the registered item number. While the item number and account identifier is a straight validation, the key will be used to decrypt and view the stored **\"Certificate of Authenticity or image\"**. If decryption fails, then it assumes that the owner is not the legal owner of the Asset.\r\n\r\n## APIs Available\r\nThe following Invoke and Query APIs are available from both CLI and REST, and have the following signature\r\n\r\n    func(stub *shim.ChaincodeStub, function string, args []string) ([]byte, error) \r\n\r\n### Invoke\r\n                * iPostUser \r\n                * iPostItem\r\n                * iPostAuctionRequest\r\n                * iPostTransaction\r\n                * iPostBid\r\n                * iOpenAuctionForBids\r\n                * iBuyItNow\r\n                * iTransferItem\r\n                * iCloseAuction\r\n                * iCloseOpenAuctions\r\n### Query\r\n                * qGetItem\r\n                * qGetUser\r\n                * qGetAuctionRequest\r\n                * qGetTransaction\r\n                * qGetBid\r\n                * qGetLastBid\r\n                * qGetHighestBid\r\n                * qGetNoOfBidsReceived\r\n                * qGetListOfBids\r\n                * qGetItemLog\r\n                * qGetItemListByCat\r\n                * qGetUserListByCat\r\n                * qGetListOfItemsOnAuc\r\n                * qGetListOfOpenAucs\r\n                * qValidateItemOwnership\r\n                * qIsItemOnAuction\r\n\r\n##Environment Setup\r\n\r\nPlease review instructions on setting up the [Development Environment](https://github.com/hyperledger/fabric/blob/master/docs/source/dev-setup/devenv.rst) as well as the setting up the [Sandbox Environment](https://github.com/hyperledger/fabric/blob/master/docs/source/Setup/Chaincode-setup.rst) to execute the chaincode.\r\n\r\n## Running the Application\r\n\r\n** Fork and clone the fabric**\r\n```\r\n git clone https://github.com/hyperledger/fabric.git\r\n cd $GOPATH/src/github.com/hyperledger/fabric\r\n Fork Auction git repository from here https://github.com/ITPeople-Blockchain/auction.git and clone from your remote auction repository\r\n git clone https://github.com/<username>/auction.git\r\n```\r\n\r\nExecute below command to clear production data \r\n\r\n`rm -rf /var/hyperledger/*`\r\n\r\n###Terminal 1\r\n\r\nBuild peer and Orderer binaries and Start Orderer\r\n\r\n```\r\n cd $GOPATH/src/github.com/hyperledger/fabric\r\n make native\r\n orderer\r\n```\r\n\r\n###Terminal 2\r\n\r\nStart Peer\r\n```\r\n cd $GOPATH/src/github.com/hyperledger/fabric\r\n peer node start -o 127.0.0.1:7050\r\n```\r\n###Terminal 3\r\n```\r\n cd $GOPATH/src/github.com/hyperledger/fabric/auction/art/scripts\r\n Run env.sh script to export CORE_PEER_MSPCONFIGPATH\r\n `source env.sh`\r\n```\r\n###Run the following shell scripts\r\n\r\nThe scripts are provided for the convenience of understanding how to use the application as well as testing in your specific cloned environment. The scripts execute all API calls in CLI mode. In CLI mode, the peer and the chaincode live within the same container. However, these scripts will not work well in NET mode. To test the application in NET mode, follow the instructions on using the UI to make the API calls.\r\n\r\n#### PostUsers\r\n\r\nThe PostUsers script inserts a set of users into the database. Today, the only validation done is to check if the user \r\nID is an integer.\r\nTODO: In a future version, the user identity will be validated against the IDaaS Blockchain prior to \r\ninserting into the database\r\n\r\n`./PostUsers`\r\n\r\n#### PostItems\r\n\r\nThe PostItems script inserts a set of ART ASSETS into the database. Before inserting the asset the chaincode checks \r\nif the CurrentOwner is registered as a User. Based on the image file name (in future this could be a title or some\r\nownership document) is retrieved and converted to a byte array ([]byte). An AES Key is generated, the byte array is encrypted\r\nand both key and the byte array are saved in the database.A log entry is made in the Item Log. \r\nPlease see code for detailed comments\r\n\r\n`./PostItems`\r\n\r\nIn the business process, the owner (User ID# 100) of the ASSET (Item# 1000) requests an entity like an Auction House (User ID# 200) to put the item on auction. Before Posting the auction request, the Asset is validated against the database. The Auction House ID is verified in the User Table. A log entry is made in the Item Log.\r\n\r\nTODO: In future, the owner of the asset will present his key to help with validation. \r\nThe AES key will be used to un-encrypt the stored image and authenticate ASSET ownership. \r\n\r\n#### PostAuctionRequest\r\n\r\nWhen the ASSET OWNER  of an item is ready to place his item on auction, he/she would identify an Auction House, determine what the reserve price should be and send a request to the Auction House expressing interest in placing their item on the auction block. \r\n\r\n`./PostAuctionRequest`\r\n\r\n#### OpenAuctionRequestForBids\r\n\r\nThe Auction House, we assume will inspect the physical item, the certificate of authenticity, the ownership key and other details. They would also run a valuation of the item to determine if the reserve price is valid. The application assumes these have occurred outside of the scope of the application\r\n\r\nEven though the ASSET OWNER has requested the Auction House to place the item on auction, the Auction is not yet open for acceptance of user bids. Hence any bid submitted against the item will be rejected if the auction is not open\r\nThis script opens the Auction Request for bids. It sets the status of the AuctionRequest to \"OPEN\". It opens a timer for \r\nthe duration of the auction which in the example is 3 minutes. During this window, any user can submit bids against the AuctionID. Once the timer expires, a script is created and saved called \"CloseAuction.sh\". The script gets triggered. \r\n\r\n##### CloseAuction\r\n\r\nThe CloseAuction.sh script invokes CloseAuction. \r\nCloseAuction will first change the status of the AuctionRequest to \"CLOSED\". It then fetches the highest bid from the list of bids received, and converts it to a Transaction. The transaction is posted, the ASSET is retrieved from the database, its price is set to the new Hammer Price and the CurrentOwner is set to the new buyer. The ASSET image is un-encrypted with the old key, a new Key is generated and the image is encrypted with the new key. The ASSET is updated in the database.\r\nAn log entry is made in the Item Log.\r\n\r\nTODO: In future, the Transaction will be a business document that triggers payments, shipping,insurance and commissions\r\n\r\n`./OpenAuctionRequestForBids`\r\n\r\nOpens the auction request for bids for 3 minutes - Auction Request ID used for testing is 1111 and Item 1000\r\nThis opens a timer for 3 minutes and once timer expires, writes a shell script to invoke CloseAuction...\r\n\r\nAs described above, once the auction is \"OPEN\", this script submits bids against that auctionID. Both the auctionID and the buyerID are validated before the bid is posted. Once the auction is \"CLOSED\", new bids will be rejected\r\n\r\n`./Submitbids`\r\n  submits a series of bids against auction# 1111 and item# 1000\r\n\r\n`./SubmitQueries`\r\n  This is list of queries that can be issued and must be used via cut and paste on command line (CLI)\r\n\r\nAfter the timer expires, the Close auction should get invoked and the highest bid should be posted as a transaction\r\n\r\n## Invoke APIs and usage\r\n**PostUser**:\r\n\r\n   This function is used to register an Account for any of the stakeholders defined earlier\r\n\r\n   **Usage (CLI mode)**\r\n\r\n   The call takes 9 arguments: User ID, Record Type, Name, Type, Address, Phone, Email, Bank Name, Account#, Routing#\r\n   \r\n   peer chaincode invoke -l golang -n mycc -c '{\"Function\": \"PostUser\", \"Args\":[\"100\", \"USER\", \"Ashley Hart\", \"TRD\",  \"Morrisville Parkway, #216, Morrisville, NC 27560\", \"9198063535\", \"ashley@itpeople.com\", \"SUNTRUST\", \"00017102345\", \"0234678\"]}'\r\n\r\n**PostItem**:\r\n\r\n   This function is used to register an Asset with the blockchain. The owner of the Asset must have a registered account prior to registering the Asset. No validation of the \"User Type\" is done by the chaincode and should be managed outside by the client. The name of the image (f6.png) is uploaded by the chaincode from a pre-determined directory, converted to []byte, encrypted using AES and stored in the blockchain.\r\n\r\n   **Usage (CLI mode)**\r\n\r\n   The call takes 12 arguments: Item ID, Record Type, Description, Detail, Date of Origin, Original or Reprint, Subject, Media, Size, Image File, Price, Current Owner ID\r\n   \r\n   peer chaincode invoke -l golang -n mycc -c '{\"Function\": \"PostItem\", \"Args\":[\"1400\", \"ARTINV\", \"Nature\", \"James Thomas\", \"19900115\", \"Original\", \"modern\", \"Water Color\", \"12 x 17 in\", \"f6.png\",\"1800\", \"100\"]}'\r\n\r\n**PostAuctionRequest**:\r\n\r\n   This function is used by the owner of an Asset to request an Auction House to accept the Asset for auction. The Auction House ID, the owner ID and the asset ID are all validated before a request can be posted. Posting a request does not mean bids can be accepted. The auction has to be opened in order for bids to be accepted or \"Buy It Now\" to happen.\r\n\r\n   **Usage (CLI mode)**\r\n\r\n   This call takes 11 argumnets: Auction ID, Record Type, Item ID, Auction House ID, Owner ID, Date of Request, Reserve Price, Buy-It-Now Price, Status, Dummy Open Date, Dummy Close Date\r\n   \r\n   peer chaincode invoke -l golang -n mycc -c '{\"Function\": \"PostAuctionRequest\", \"Args\":[\"1113\", \"AUCREQ\", \"1000\", \"200\", \"400\", \"04012016\", \"15000\", \"16000\", \"INIT\", \"2016-05-20 11:00:00.3 +0000 UTC\",\"2016-05-23 11:00:00.3 +0000 UTC\"]}'\r\n\r\n   The Auction Opendate and CloseDate are dummy dates and will be set when the auction is opened. The Auction ID must be unique and cannot be repeated. We assume that the client will generate a unique auction id prior to posting the request. The state of the Auction is \"INIT\" at this point.\r\n\r\n**OpenAuctionForBids**:\r\n\r\n   This function is assumed to be invoked by the role of \"Auction House\" which is one of the types of accounts registered using PostUser. It allows the auctioner to open an auction for bids. The auction request must be in \"INIT\" state to be \"OPEN\"ed. When the auction is opened for bids, both the open and close date and time are set. The following example opens the bid for 3 minutes. Auction open durations are currently provided in minutes to support testing.\r\n\r\n   **Usage (CLI mode)**\r\n\r\n   The call takes 3 arguments: Auction ID, Record Type, Duration in Minutes\r\n   \r\n   peer chaincode invoke -l golang -n mycc -c '{\"Function\": \"OpenAuctionForBids\", \"Args\":[\"1111\", \"OPENAUC\", \"3\"]}'\r\n\r\n**PostBid**:\r\n\r\n   This function allows a potential buyer to bid on the Asset once the auction is open. Every bid is checked for valid auction ID, asset ID and buyer ID. Bids must be higher than reserve price. Bids are accepted as long as the auction is \"OPEN\". Bid numbers must be unique and generated by the client.\r\n\r\n   **Usage (CLI mode)**\r\n\r\n   This call takes 6 arguments: Auction ID, Record Type, Bid Number, Item ID, Buyer ID, Buyer Offer Price\r\n   \r\n   peer chaincode invoke -l golang -n mycc -c '{\"Function\": \"PostBid\", \"Args\":[\"1111\", \"BID\", \"5\", \"1000\", \"400\", \"5000\"]}'\r\n\r\n**PostTransaction**:\r\n\r\n   Even though the Transaction is automatically generated and posted when one of the following events occur: \r\n   * Auction closes after the auction timer expires (Only CLI Mode)\r\n   * A message to close all expired auctions are close is issued by the client via \"CloseOpenAuctions\"\r\n   * A \"BuyItNow\" call is made which goes through \r\n   this function is exposed as a matter of convenience just in case transactions don't get posted properly. \r\n   When a Transaction is posted, it updates the Asset with the new buyer ID, re-generates a new key and encrypts the image/certificate and updates the asset price to the \"Hammer Price\". It also adds a new entry into the item history table.\r\n\r\n   **Usage (CLI mode)**\r\n\r\n   This call takes 8 arguments: Auction ID, Record Type, Item ID, Transaction Type, Buyer ID, Transaction Time, Hammer Time, Hammer Price\r\n   \r\n   peer chaincode invoke -l golang -n mycc -c '{\"Function\": \"PostBid\", \"Args\":[\"1111\", \"POSTTRAN\", \"1000\", \"SALE\",\"500\", \"2016-05-24 11:00:00\",\"2016-05-23 14:25:00\", \"12000\"]}'\r\n\r\n**BuyItNow**:\r\n\r\n   Sometimes, an asset owner can specify a \"Buy It Now\" price in addition to the \"Reserve Price\" while posting an auction request. If an asset has a \"Buy It Now\" price, a buyer can issue a \"BuyItNow\" call. If there are no bids higher than the \"BuyItNow\" price, the request will be rejected. If the request goes through, the auction is closed and a transaction is posted against the buyer. \r\n\r\n   **Usage (CLI mode)**\r\n\r\n   This call is similar to the PostBid, except the price is set to the Buy-It-Now price.\r\n\r\n   peer chaincode invoke -l golang -n mycc -c '{\"Function\": \"BuyItNow\", \"Args\":[\"1111\", \"BID\", \"1\", \"1000\", \"300\", \"1800\"]}'\r\n\r\n**TransferItem**:\r\n\r\n   At any time, the current owner of an asset can transfer the item at no additional cost or change in value to another user, provided the asset is not initiated for auctions, or is in the process of an auction. Smart contract rules may have to be written to comply with local regulations and taxes. The current owner has to prove ownership by providing his key. The owner id, item id and the key are all validated before transfer can take place. The new owner will receive a new key.\r\n\r\n   **Usage (CLI mode)**\r\n\r\n   This call takes 5 arguments: Item ID, Current Owner ID, Owner Key, Transferee ID, Record Type\r\n   \r\n   peer chaincode invoke -l golang -n mycc -c '{\"Function\": \"TransferItem\", \"Args\": [\"1000\", \"100\", \"218MC/ipIsIrDhE9TKXqG2NsWl7KSE59Y3UmwBzSrQo=\", \"300\", \"XFER\"]}'\r\n\r\n**CloseAuction**:\r\n\r\n   This function call closes an auction once the time expires. This call is automatically issued in \"CLI\" mode since the \"OpenAuctionForBids\" call triggers a go routine that sleeps for the duration of the auction and the automatically issues a \"CloseAuction\" call. This functions closes the auction request, picks the highest bid and creates a transaction an then posts the transaction.\r\n\r\n   **Usage (CLI mode)**\r\n\r\n   This call takes two arguments: Auction ID, Record Type\r\n   \r\n   peer chaincode invoke -l golang -n mycc -c '{\"Function\": \"CloseAuction\", \"Args\": [\"1111\",\"AUCREQ\"]}'\r\n\r\n**CloseOpenAuctions**:\r\n\r\n   This is a function designed specifically for Bluemix situations where the peer and the chaincode run in different containers, hence a call as shown in each of \"Usage (CLI mode)\" will not work. This function is issued periodically by the client (UI or applications consuming the blockchain) as a REST call. The functions checks for auctions whose time has run-out and closes them.\r\n\r\n   **Usage (CLI mode)**\r\n\r\n   This call takes two arguments: 2016, Record Type\r\n   \r\n   peer chaincode invoke -l golang -n mycc -c '{\"Function\": \"CloseOpenAuctions\", \"Args\": [\"2016\", \"CLAUC\"]}'\r\n\r\n###Query APIs and Usage\r\n\r\n**GetItem**:\r\n\r\n   Retrieves an Asset record by asset ID.\r\n\r\n   **Usage (CLI mode)**\r\n\r\n      peer chaincode query -l golang -n mycc -c '{\"Function\": \"GetItem\", \"Args\": [\"1000\"]}'\r\n \r\n**GetUser**:\r\n\r\n   Retrieves an user record by user or stakeholder ID.\r\n\r\n   **Usage (CLI mode)**\r\n\r\n      peer chaincode query -l golang -n mycc -c '{\"Function\": \"GetUser\", \"Args\": [\"100\"]}'\r\n   \r\n**GetAuctionRequest**:\r\n\r\n   Retrieves an auction request by auction request ID.\r\n\r\n   **Usage (CLI mode)**\r\n\r\n      peer chaincode query -l golang -n mycc -c '{\"Function\": \"GetAuctionRequest\", \"Args\": [\"1111\"]}'\r\n\r\n**GetTransaction**:\r\n\r\n   Retrieves an transaction posted against an auction by auction request ID and asset ID.\r\n\r\n   **Usage (CLI mode)**\r\n\r\n      peer chaincode query -l golang -n mycc -c '{\"Function\": \"GetTransaction\", \"Args\": [\"1111\", \"1000\"]}'\r\n\r\n**GetBid**:\r\n\r\n   Retrieves a single bid by auction ID and bid number\r\n\r\n   **Usage (CLI mode)**\r\n\r\n      peer chaincode query -l golang -n mycc -c '{\"Function\": \"GetBid\",  \"Args\": [\"1111\", \"5\"]}'\r\n   \r\n**GetLastBid**:\r\n\r\n   Retrieves the last submitted bid. Since bids are submitted in random , and the only requirement is that the bid price be higher than the reserve price, the last received bid need not be the highest bid.\r\n\r\n   **Usage (CLI mode)**\r\n\r\n      peer chaincode query -l golang -n mycc -c '{\"Function\": \"GetLastBid\",\"Args\": [\"1111\"]}'\r\n\r\n**GetHighestBid**:\r\n\r\n   Retrieves the highest bid submitted against the auction thus far. If the auction has expired, then the highest bid is the highest bid for the auction.\r\n\r\n   **Usage (CLI mode)**\r\n\r\n      peer chaincode query -l golang -n mycc -c '{\"Function\": \"GetHighestBid\", \"Args\": [\"1111\"]}'\r\n   \r\n**GetNoOfBidsReceived**:\r\n\r\n   Retrieves the total number of bids received at any point in time. If the auction has expired, it represents the total number of bids received against that auction.\r\n\r\n   **Usage (CLI mode)**\r\n\r\n      peer chaincode query -l golang -n mycc -c '{\"Function\": \"GetNoOfBidsReceived\", \"Args\": [\"1111\"]}'\r\n\r\n**GetListOfBids**:\r\n   \r\n   Retrieves all the bids received against an auction. each row in the list represents a bid object.\r\n\r\n   **Usage (CLI mode)**\r\n\r\n      peer chaincode query -l golang -n mycc -c '{\"Function\": \"GetListOfBids\", \"Args\": [\"1111\"]}'\r\n\r\n**GetItemLog**:\r\n\r\n   Retrieves the history of an asset. The log is updated when an asset is registered, put on auction, post auction, transfered etc.\r\n\r\n   **Usage (CLI mode)**\r\n\r\n      peer chaincode query -l golang -n mycc -c '{\"Function\": \"GetItemLog\",\"Args\": [\"1000\"]}'\r\n   \r\n**GetItemListByCat**:\r\n\r\n   Retrieves a list of assets by asset category. If only the first key is provided, the query retrieves all assets. \"2016\" is hard-coded as a fixed first key. This is a band-aid solution to retrieve all records. This is a band-aid solution to retrieve all records. The following query retrieves all assets of category \"modern\".\r\n\r\n   **Usage (CLI mode)**\r\n\r\n      peer chaincode query -l golang -n mycc -c '{\"Function\": \"GetItemListByCat\",\"Args\": [\"2016\", \"modern\"]}'\r\n\r\n**GetUserListByCat**:\r\n\r\n   Retrieves a list of stakeholders or account holders by stakeholder type. If only the first key is provided, the query retrieves all assets. \"2016\" is hard-coded as a fixed first key. This is a band-aid solution to retrieve all records. The following query retrieves all stakeholders of type \"AH\" or auction houses.\r\n\r\n   **Usage (CLI mode)**\r\n\r\n      peer chaincode query -l golang -n mycc -c '{\"Function\": \"GetItemListByCat\",\"Args\": [\"2016\", \"AH\"]}'\r\n\r\n**GetListOfInitAucs**:\r\n\r\n   This query retrieves all assets which have been submitted for auction. Their status is \"Init\". The \"2016\" is a fixed key to denote all auctions in 2016.\r\n\r\n   **Usage (CLI mode)**\r\n\r\n      peer chaincode query -l golang -n mycc -c '{\"Function\": \"GetListOfInitAucs\",\"Args\": [\"2016\"]}'\r\n   \r\n**GetListOfOpenAucs**:\r\n\r\n   This query retrieves a list of all assets whose auctions have been \"OPEN\"ed for receiving bids. The \"2016\" is a fixed key to denote all auctions in 2016.\r\n\r\n   **Usage (CLI mode)**\r\n\r\n      peer chaincode query -l golang -n mycc -c '{\"Function\": \"GetListOfOpenAucs\", \"Args\": [\"2016\"]}'\r\n   \r\n**ValidateItemOwnership**:\r\n\r\n   Validates the ownership of an asset. Checks for valid account id, asset id and retrieves asset from blockchain using the owners's key. The arguments are Item ID, Current Owner ID and Owner's Key.\r\n\r\n   **Usage (CLI mode)**\r\n\r\n      peer chaincode query -l golang -n mycc -c '{\"Function\": \"ValidateItemOwnership\",   \"Args\": [\"1000\", \"500\", \"avQX6JfTnELAY4mkRhOr8P7vmz0H3aAIuFGsGiSD5UQ=\"]}'\r\n\r\n**IsItemOnAuction**:\r\n\r\n   Checks whether an Asset has an **auction request** posted, or currently on auction and returns a boolean true or false.\r\n\r\n   **Usage (CLI mode)**\r\n\r\n      peer chaincode query -l golang -n mycc -c '{\"Function\": \"IsItemOnAuction\", \"Args\": [\"1999\", \"VERIFY\"]}'\r\n\r\n##Notes\r\n\r\n* Once an auction request is posted or an auction is open for bids, there is no api to remove the auction request or close the auction prematurely and rejecting all bids received\r\n* In the current version, the image is encrypted and stored in the blockchain. However, in future, it is envisioned that only the hash of the image  along with the URI to the location of the image will be saved\r\n\r\n##Runnning the Application using the Web Browser\r\n\r\nThe chaincode functions can be accessed via the browser, Please refer [auction-app](https://github.com/ITPeople-Blockchain/auction-app) for more details.\r\n"
  },
  {
    "path": "mkdocs.yml",
    "content": "site_name: ITPeople Blockchain Auction\nsite_url: http://itpeople-blockchain-auction.readthedocs.org\ntheme: readthedocs\nrepo_url: https://github.com/ITPeople-Blockchain/auction\nsite_description: 'Welcome to the ITPeople Blockchain Art Auction Application documentation'\nmarkdown_extensions:\n# Convert ASCII dashes, quotes to HTML entity\n- smarty\n\npages:\n- HOME: index.md\n"
  }
]