Compare commits
2 commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
9792677030 | ||
![]() |
933e063af6 |
226
chaincode_example02.go
Normal file
226
chaincode_example02.go
Normal file
|
@ -0,0 +1,226 @@
|
|||
/*
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/hyperledger/fabric/core/chaincode/shim"
|
||||
)
|
||||
|
||||
// SimpleChaincode example simple Chaincode implementation
|
||||
type SimpleChaincode struct {
|
||||
}
|
||||
|
||||
func (t *SimpleChaincode) Init(stub *shim.ChaincodeStub, function string, args []string) ([]byte, error) {
|
||||
fmt.Printf("Init called, initializing chaincode")
|
||||
|
||||
var A, B string // Entities
|
||||
var Aval, Bval int // Asset holdings
|
||||
var err error
|
||||
|
||||
if len(args) != 4 {
|
||||
return nil, errors.New("Incorrect number of arguments. Expecting 4")
|
||||
}
|
||||
|
||||
// Initialize the chaincode
|
||||
A = args[0]
|
||||
Aval, err = strconv.Atoi(args[1])
|
||||
if err != nil {
|
||||
return nil, errors.New("Expecting integer value for asset holding")
|
||||
}
|
||||
B = args[2]
|
||||
Bval, err = strconv.Atoi(args[3])
|
||||
if err != nil {
|
||||
return nil, errors.New("Expecting integer value for asset holding")
|
||||
}
|
||||
fmt.Printf("Aval = %d, Bval = %d\n", Aval, Bval)
|
||||
|
||||
// Write the state to the ledger
|
||||
err = stub.PutState(A, []byte(strconv.Itoa(Aval)))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = stub.PutState(B, []byte(strconv.Itoa(Bval)))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Transaction makes payment of X units from A to B
|
||||
func (t *SimpleChaincode) invoke(stub *shim.ChaincodeStub, args []string) ([]byte, error) {
|
||||
fmt.Printf("Running invoke")
|
||||
|
||||
var A, B string // Entities
|
||||
var Aval, Bval int // Asset holdings
|
||||
var X int // Transaction value
|
||||
var err error
|
||||
|
||||
if len(args) != 3 {
|
||||
return nil, errors.New("Incorrect number of arguments. Expecting 3")
|
||||
}
|
||||
|
||||
A = args[0]
|
||||
B = args[1]
|
||||
|
||||
// Get the state from the ledger
|
||||
// TODO: will be nice to have a GetAllState call to ledger
|
||||
Avalbytes, err := stub.GetState(A)
|
||||
if err != nil {
|
||||
return nil, errors.New("Failed to get state")
|
||||
}
|
||||
if Avalbytes == nil {
|
||||
return nil, errors.New("Entity not found")
|
||||
}
|
||||
Aval, _ = strconv.Atoi(string(Avalbytes))
|
||||
|
||||
Bvalbytes, err := stub.GetState(B)
|
||||
if err != nil {
|
||||
return nil, errors.New("Failed to get state")
|
||||
}
|
||||
if Bvalbytes == nil {
|
||||
return nil, errors.New("Entity not found")
|
||||
}
|
||||
Bval, _ = strconv.Atoi(string(Bvalbytes))
|
||||
|
||||
// Perform the execution
|
||||
X, err = strconv.Atoi(args[2])
|
||||
Aval = Aval - X
|
||||
Bval = Bval + X
|
||||
fmt.Printf("Aval = %d, Bval = %d\n", Aval, Bval)
|
||||
|
||||
// Write the state back to the ledger
|
||||
err = stub.PutState(A, []byte(strconv.Itoa(Aval)))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = stub.PutState(B, []byte(strconv.Itoa(Bval)))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Deletes an entity from state
|
||||
func (t *SimpleChaincode) delete(stub *shim.ChaincodeStub, args []string) ([]byte, error) {
|
||||
fmt.Printf("Running delete")
|
||||
|
||||
if len(args) != 1 {
|
||||
return nil, errors.New("Incorrect number of arguments. Expecting 3")
|
||||
}
|
||||
|
||||
A := args[0]
|
||||
|
||||
// Delete the key from the state in ledger
|
||||
err := stub.DelState(A)
|
||||
if err != nil {
|
||||
return nil, errors.New("Failed to delete state")
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Invoke callback representing the invocation of a chaincode
|
||||
// This chaincode will manage two accounts A and B and will transfer X units from A to B upon invoke
|
||||
func (t *SimpleChaincode) Invoke(stub *shim.ChaincodeStub, function string, args []string) ([]byte, error) {
|
||||
fmt.Printf("Invoke called, determining function")
|
||||
|
||||
// Handle different functions
|
||||
if function == "invoke" {
|
||||
// Transaction makes payment of X units from A to B
|
||||
fmt.Printf("Function is invoke")
|
||||
return t.invoke(stub, args)
|
||||
} else if function == "init" {
|
||||
fmt.Printf("Function is init")
|
||||
return t.Init(stub, function, args)
|
||||
} else if function == "delete" {
|
||||
// Deletes an entity from its state
|
||||
fmt.Printf("Function is delete")
|
||||
return t.delete(stub, args)
|
||||
}
|
||||
|
||||
return nil, errors.New("Received unknown function invocation")
|
||||
}
|
||||
|
||||
func (t* SimpleChaincode) Run(stub *shim.ChaincodeStub, function string, args []string) ([]byte, error) {
|
||||
fmt.Printf("Run called, passing through to Invoke (same function)")
|
||||
|
||||
// Handle different functions
|
||||
if function == "invoke" {
|
||||
// Transaction makes payment of X units from A to B
|
||||
fmt.Printf("Function is invoke")
|
||||
return t.invoke(stub, args)
|
||||
} else if function == "init" {
|
||||
fmt.Printf("Function is init")
|
||||
return t.Init(stub, function, args)
|
||||
} else if function == "delete" {
|
||||
// Deletes an entity from its state
|
||||
fmt.Printf("Function is delete")
|
||||
return t.delete(stub, args)
|
||||
}
|
||||
|
||||
return nil, errors.New("Received unknown function invocation")
|
||||
}
|
||||
|
||||
// Query callback representing the query of a chaincode
|
||||
func (t *SimpleChaincode) Query(stub *shim.ChaincodeStub, function string, args []string) ([]byte, error) {
|
||||
fmt.Printf("Query called, determining function")
|
||||
|
||||
if function != "query" {
|
||||
fmt.Printf("Function is query")
|
||||
return nil, errors.New("Invalid query function name. Expecting \"query\"")
|
||||
}
|
||||
var A string // Entities
|
||||
var err error
|
||||
|
||||
if len(args) != 1 {
|
||||
return nil, errors.New("Incorrect number of arguments. Expecting name of the person to query")
|
||||
}
|
||||
|
||||
A = args[0]
|
||||
|
||||
// Get the state from the ledger
|
||||
Avalbytes, err := stub.GetState(A)
|
||||
if err != nil {
|
||||
jsonResp := "{\"Error\":\"Failed to get state for " + A + "\"}"
|
||||
return nil, errors.New(jsonResp)
|
||||
}
|
||||
|
||||
if Avalbytes == nil {
|
||||
jsonResp := "{\"Error\":\"Nil amount for " + A + "\"}"
|
||||
return nil, errors.New(jsonResp)
|
||||
}
|
||||
|
||||
jsonResp := "{\"Name\":\"" + A + "\",\"Amount\":\"" + string(Avalbytes) + "\"}"
|
||||
fmt.Printf("Query Response:%s\n", jsonResp)
|
||||
return Avalbytes, nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
err := shim.Start(new(SimpleChaincode))
|
||||
if err != nil {
|
||||
fmt.Printf("Error starting Simple chaincode: %s", err)
|
||||
}
|
||||
}
|
186
develop/Asset_&_Method_Definitions.go
Normal file
186
develop/Asset_&_Method_Definitions.go
Normal file
|
@ -0,0 +1,186 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/hyperledger/fabric/core/chaincode/shim"
|
||||
pb "github.com/hyperledger/fabric/protos/peer"
|
||||
)
|
||||
|
||||
// SimpleChaincode example simple Chaincode implementation
|
||||
type SimpleChaincode struct {
|
||||
}
|
||||
|
||||
|
||||
// ============================================================================================================================
|
||||
// Asset Definitions - The ledger will store wallets and owners
|
||||
// ============================================================================================================================
|
||||
|
||||
// ----- Wallets ----- //
|
||||
type Wallet struct {
|
||||
ObjectType string `json:"docType"`
|
||||
Id string `json:"id"`
|
||||
Balance int `json:"balance"`
|
||||
Owner OwnerRelation `json:"owner"`
|
||||
}
|
||||
|
||||
// ----- Beneficiaries ----- //
|
||||
type Beneficiary struct {
|
||||
ObjectType string `json:"docType"`
|
||||
Id string `json:"id"`
|
||||
IdBenef string `json:"idbenef`
|
||||
NameBenef string `json:"namebenef"`
|
||||
FirstnameBenef string `json:"firstnamebenef"`
|
||||
Owner OwnerRelation `json:"owner"`
|
||||
}
|
||||
|
||||
// ----- Owners ----- //
|
||||
type Owner struct {
|
||||
ObjectType string `json:"docType"`
|
||||
Id string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Firstname string `json:"firstname"`
|
||||
Mail string `json:"mail"`
|
||||
Address string `json:"address"`
|
||||
City string `json:"city"`
|
||||
Postalcode int `json:"postal"`
|
||||
Password string `json:"password"`
|
||||
Association string `json:"association"`
|
||||
//disabled owners will not be visible to the application
|
||||
Enabled bool `json:"enabled"`
|
||||
}
|
||||
|
||||
type OwnerRelation struct {
|
||||
Id string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Firstname string `json:"firstname"`
|
||||
}
|
||||
|
||||
|
||||
// ============================================================================================================================
|
||||
// Main
|
||||
// ============================================================================================================================
|
||||
func main() {
|
||||
err := shim.Start(new(SimpleChaincode))
|
||||
if err != nil {
|
||||
fmt.Printf("Error starting Simple chaincode - %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ============================================================================================================================
|
||||
// Init - initialize the chaincode
|
||||
//
|
||||
// Returns - shim.Success or error
|
||||
// ============================================================================================================================
|
||||
func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface) pb.Response {
|
||||
fmt.Println("Wallet Is Starting Up")
|
||||
funcName, args := stub.GetFunctionAndParameters()
|
||||
var number int
|
||||
var err error
|
||||
txId := stub.GetTxID()
|
||||
|
||||
fmt.Println("Init() is running")
|
||||
fmt.Println("Transaction ID:", txId)
|
||||
fmt.Println(" GetFunctionAndParameters() function:", funcName)
|
||||
fmt.Println(" GetFunctionAndParameters() args count:", len(args))
|
||||
fmt.Println(" GetFunctionAndParameters() args found:", args)
|
||||
|
||||
// expecting 1 arg for instantiate or upgrade
|
||||
if len(args) == 1 {
|
||||
fmt.Println(" GetFunctionAndParameters() arg[0] length", len(args[0]))
|
||||
|
||||
// expecting arg[0] to be length 0 for upgrade
|
||||
if len(args[0]) == 0 {
|
||||
fmt.Println("args[0] is empty...")
|
||||
} else {
|
||||
fmt.Println(" Great news everyone, args[0] is not empty")
|
||||
|
||||
// convert numeric string to integer
|
||||
number, err = strconv.Atoi(args[0])
|
||||
if err != nil {
|
||||
return shim.Error("Expecting a numeric string argument to Init() for instantiate")
|
||||
}
|
||||
|
||||
// this is a very simple test. let's write to the ledger and error out on any errors
|
||||
// it's handy to read this right away to verify network is healthy if it wrote the correct value
|
||||
err = stub.PutState("selftest", []byte(strconv.Itoa(number)))
|
||||
if err != nil {
|
||||
return shim.Error(err.Error()) //self-test fail
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// showing the alternative argument shim function
|
||||
alt := stub.GetStringArgs()
|
||||
fmt.Println(" GetStringArgs() args count:", len(alt))
|
||||
fmt.Println(" GetStringArgs() args found:", alt)
|
||||
|
||||
// store compatible wallet application version
|
||||
err = stub.PutState("wallets_ui", []byte("4.0.1"))
|
||||
if err != nil {
|
||||
return shim.Error(err.Error())
|
||||
}
|
||||
|
||||
fmt.Println("Ready for action") //self-test pass
|
||||
return shim.Success(nil)
|
||||
}
|
||||
|
||||
|
||||
// ============================================================================================================================
|
||||
// Invoke - Our entry point for Invocations
|
||||
// ============================================================================================================================
|
||||
func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
|
||||
function, args := stub.GetFunctionAndParameters()
|
||||
fmt.Println(" ")
|
||||
fmt.Println("starting invoke, for - " + function)
|
||||
|
||||
// Handle different functions
|
||||
if function == "init" { //initialize the chaincode state, used as reset
|
||||
return t.Init(stub)
|
||||
} else if function == "read" { //generic read ledger
|
||||
return read(stub, args)
|
||||
} else if function == "write" { //generic writes to ledger
|
||||
return write(stub, args)
|
||||
} else if function == "delete_wallet" { //deletes a wallet from state
|
||||
return delete_wallet(stub, args)
|
||||
} else if function == "delete_owner" { //deletes an owner from state
|
||||
return delete_owner(stub, args)
|
||||
} else if function == "delete_beneficiary" { //deletes a beneficiary from state
|
||||
return delete_beneficiary(stub, args)
|
||||
} else if function == "init_wallet" { //create a new wallet
|
||||
return init_wallet(stub, args)
|
||||
} else if function == "init_owner"{ //create a new wallet owner
|
||||
return init_owner(stub, args)
|
||||
} else if function == "init_beneficiary" { //create a new beneficiary
|
||||
return init_beneficiary(stub, args)
|
||||
} else if function == "set_owner" { //change owner of a wallet
|
||||
return set_owner(stub, args)
|
||||
} else if function == "set_beneficiary" { //change owner of a wallet
|
||||
return set_beneficiary(stub, args)
|
||||
} else if function == "disable_owner"{ //disable a wallet owner from appearing on the UI
|
||||
return disable_owner(stub, args)
|
||||
} else if function == "transfer"{ //transfer X Units From a User to an other
|
||||
return transfer(stub, args)
|
||||
} else if function == "get_wallet"{ //get wallets
|
||||
return get_wallet(stub, args)
|
||||
} else if function == "get_owner"{ //get owners
|
||||
return get_owner(stub, args)
|
||||
} else if function == "get_beneficiary"{ //get beneficiaries
|
||||
return get_beneficiary(stub, args)
|
||||
} else if function == "get_transaction"{ //get transactions
|
||||
return get_transaction(stub, args)
|
||||
|
||||
// error out
|
||||
fmt.Println("Received unknown invoke function name - " + function)
|
||||
return shim.Error("Received unknown invoke function name - '" + function + "'")
|
||||
}
|
||||
|
||||
|
||||
// ============================================================================================================================
|
||||
// Query - legacy function
|
||||
// ============================================================================================================================
|
||||
func (t *SimpleChaincode) Query(stub shim.ChaincodeStubInterface) pb.Response {
|
||||
return shim.Error("Unknown supported call - Query()")
|
||||
}
|
132
develop/Get_Class.go
Normal file
132
develop/Get_Class.go
Normal file
|
@ -0,0 +1,132 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"strconv"
|
||||
|
||||
"github.com/hyperledger/fabric/core/chaincode/shim"
|
||||
)
|
||||
|
||||
|
||||
// ============================================================================================================================
|
||||
// Get Wallet - get a wallet asset from ledger
|
||||
// ============================================================================================================================
|
||||
func get_wallet(stub shim.ChaincodeStubInterface, id string) (Wallet, error) {
|
||||
var wallet Wallet
|
||||
|
||||
//getState retreives a key/value from the ledger
|
||||
walletAsBytes, err := stub.GetState(id)
|
||||
if err != nil {
|
||||
return wallet, errors.New("Failed to find wallet - " + id)
|
||||
}
|
||||
|
||||
//un stringify it aka JSON.parse()
|
||||
json.Unmarshal(walletAsBytes, &wallet)
|
||||
|
||||
//test if wallet is actually here or just nil
|
||||
if wallet.Id != id {
|
||||
return wallet, errors.New("Wallet does not exist - " + id)
|
||||
}
|
||||
|
||||
return wallet, nil
|
||||
}
|
||||
|
||||
|
||||
// ============================================================================================================================
|
||||
// Get Owner - get the owner asset from ledger
|
||||
// ============================================================================================================================
|
||||
func get_owner(stub shim.ChaincodeStubInterface, id string) (Owner, error) {
|
||||
var owner Owner
|
||||
|
||||
ownerAsBytes, err := stub.GetState(id)
|
||||
if err != nil {
|
||||
return owner, errors.New("Failed to get owner - " + id)
|
||||
}
|
||||
|
||||
json.Unmarshal(ownerAsBytes, &owner)
|
||||
|
||||
//test if owner is actually here or just nil
|
||||
if len(owner.Username) == 0 {
|
||||
return owner, errors.New("Owner does not exist - " + id + ", '" + owner.Username "'")
|
||||
}
|
||||
|
||||
return owner, nil
|
||||
}
|
||||
|
||||
|
||||
// ============================================================================================================================
|
||||
// Get Beneficiary - get the beneficiaries asset from ledger
|
||||
// ============================================================================================================================
|
||||
func get_benefeciary(stub shim.ChaincodeStubInterface, id string) (Beneficiary, error) {
|
||||
var beneficiary Beneficiary
|
||||
|
||||
//getState retreives a key/value from the ledger
|
||||
beneficiaryAsBytes, err := stub.GetState(id)
|
||||
if err != nil {
|
||||
return beneficiary, errors.New("Failed to find beneficiary - " + id)
|
||||
}
|
||||
|
||||
json.Unmarshal(walletAsBytes, &beneficiary)
|
||||
|
||||
//test if beneficiary is actually here or just nil
|
||||
if beneficiary.Id != id {
|
||||
return beneficiary, errors.New("Beneficiary does not exist - " + id)
|
||||
}
|
||||
|
||||
return beneficiary, nil
|
||||
}
|
||||
|
||||
|
||||
// ============================================================================================================================
|
||||
// Get Transactions - get the transactions asset from ledger
|
||||
// ============================================================================================================================
|
||||
|
||||
|
||||
|
||||
// ============================================================================================================================
|
||||
// Read - read a generic variable from ledger
|
||||
//
|
||||
// Shows Off GetState() - reading a key/value from the ledger
|
||||
// ============================================================================================================================
|
||||
func read(stub shim.ChaincodeStubInterface, args []string) pb.Response {
|
||||
var key, jsonResp string
|
||||
var err error
|
||||
fmt.Println("starting read")
|
||||
|
||||
if len(args) != 1 {
|
||||
return shim.Error("Incorrect number of arguments. Expecting key of the var to query")
|
||||
}
|
||||
|
||||
// input sanitation
|
||||
err = sanitize_arguments(args)
|
||||
if err != nil {
|
||||
return shim.Error(err.Error())
|
||||
}
|
||||
|
||||
key = args[0]
|
||||
valAsbytes, err := stub.GetState(key) //get the var from ledger
|
||||
if err != nil {
|
||||
jsonResp = "{\"Error\":\"Failed to get state for " + key + "\"}"
|
||||
return shim.Error(jsonResp)
|
||||
}
|
||||
|
||||
fmt.Println("- end read")
|
||||
return shim.Success(valAsbytes) //send it onward
|
||||
}
|
||||
|
||||
|
||||
// ========================================================
|
||||
// Input Sanitation - dumb input checking, look for empty strings
|
||||
// ========================================================
|
||||
func sanitize_arguments(strs []string) error{
|
||||
for i, val:= range strs {
|
||||
if len(val) <= 0 {
|
||||
return errors.New("Argument " + strconv.Itoa(i) + " must be a non-empty string")
|
||||
}
|
||||
if len(val) > 32 {
|
||||
return errors.New("Argument " + strconv.Itoa(i) + " must be <= 32 characters")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
614
develop/Ledger_Writer_Class.go
Normal file
614
develop/Ledger_Writer_Class.go
Normal file
|
@ -0,0 +1,614 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/hyperledger/fabric/core/chaincode/shim"
|
||||
pb "github.com/hyperledger/fabric/protos/peer"
|
||||
)
|
||||
|
||||
|
||||
// ============================================================================================================================
|
||||
// write() - genric write variable into ledger
|
||||
//
|
||||
// Shows Off PutState() - writting a key/value into the ledger
|
||||
//
|
||||
// Inputs - Array of strings
|
||||
// 0 , 1
|
||||
// key , value
|
||||
// "abc" , "test"
|
||||
// ============================================================================================================================
|
||||
func write(stub shim.ChaincodeStubInterface, args []string) pb.Response {
|
||||
var key, value string
|
||||
var err error
|
||||
fmt.Println("starting write")
|
||||
|
||||
if len(args) != 2 {
|
||||
return shim.Error("Incorrect number of arguments. Expecting 2. key of the variable and value to set")
|
||||
}
|
||||
|
||||
// input sanitation
|
||||
err = sanitize_arguments(args)
|
||||
if err != nil {
|
||||
return shim.Error(err.Error())
|
||||
}
|
||||
|
||||
key = args[0]
|
||||
value = args[1]
|
||||
err = stub.PutState(key, []byte(value)) //write the variable into the ledger
|
||||
if err != nil {
|
||||
return shim.Error(err.Error())
|
||||
}
|
||||
|
||||
fmt.Println("- end write")
|
||||
return shim.Success(nil)
|
||||
}
|
||||
|
||||
|
||||
// ============================================================================================================================
|
||||
// delete_wallet() - remove a wallet from state and from wallet index
|
||||
//
|
||||
// Shows Off DelState() - "removing" a key/value from the ledger
|
||||
//
|
||||
// Inputs - Array of strings
|
||||
// 0 , 1
|
||||
// id , authorized_by_association
|
||||
// ============================================================================================================================
|
||||
func delete_wallet(stub shim.ChaincodeStubInterface, args []string) (pb.Response) {
|
||||
fmt.Println("starting delete_wallet")
|
||||
|
||||
if len(args) != 2 {
|
||||
return shim.Error("Incorrect number of arguments. Expecting 2")
|
||||
}
|
||||
|
||||
// input sanitation
|
||||
err := sanitize_arguments(args)
|
||||
if err != nil {
|
||||
return shim.Error(err.Error())
|
||||
}
|
||||
|
||||
id := args[0]
|
||||
authorized_by_association := args[1]
|
||||
|
||||
// get the wallet
|
||||
wallet, err := get_wallet(stub, id)
|
||||
if err != nil{
|
||||
fmt.Println("Failed to find wallet by id " + id)
|
||||
return shim.Error(err.Error())
|
||||
}
|
||||
|
||||
// check authorizing organisation
|
||||
if wallet.Owner.Association != authorized_by_association{
|
||||
return shim.Error("The association '" + authorized_by_association + "' cannot authorize deletion for '" + wallet.Owner.Association + "'.")
|
||||
}
|
||||
|
||||
// remove the wallet
|
||||
err = stub.DelState(id) //remove the key from chaincode state
|
||||
if err != nil {
|
||||
return shim.Error("Failed to delete state")
|
||||
}
|
||||
|
||||
fmt.Println("- end delete_wallet")
|
||||
return shim.Success(nil)
|
||||
}
|
||||
|
||||
|
||||
// ============================================================================================================================
|
||||
// delete_owner() - remove an owner from state and from owner index
|
||||
//
|
||||
// ============================================================================================================================
|
||||
func delete_owner(stub shim.ChaincodeStubInterface, args []string) (pb.Response) {
|
||||
fmt.Println("starting delete_owner")
|
||||
|
||||
if len(args) != 2 {
|
||||
return shim.Error("Incorrect number of arguments. Expecting 2")
|
||||
}
|
||||
|
||||
// input sanitation
|
||||
err := sanitize_arguments(args)
|
||||
if err != nil {
|
||||
return shim.Error(err.Error())
|
||||
}
|
||||
|
||||
id := args[0]
|
||||
authorized_by_association := args[1]
|
||||
|
||||
// get the owner
|
||||
owner, err := get_owner(stub, id)
|
||||
if err != nil{
|
||||
fmt.Println("Failed to find owner by id " + id)
|
||||
return shim.Error(err.Error())
|
||||
}
|
||||
|
||||
// check authorizing organisation
|
||||
if Owner.Association != authorized_by_association{
|
||||
return shim.Error("The association '" + authorized_by_association + "' cannot authorize deletion for '" + Owner.Association + "'.")
|
||||
}
|
||||
|
||||
// remove the owner
|
||||
err = stub.DelState(id) //remove the key from chaincode state
|
||||
if err != nil {
|
||||
return shim.Error("Failed to delete state")
|
||||
}
|
||||
|
||||
fmt.Println("- end delete_owner")
|
||||
return shim.Success(nil)
|
||||
}
|
||||
|
||||
|
||||
// ============================================================================================================================
|
||||
// delete_beneficiary() - remove a beneficiary from state and from beneficiary index
|
||||
//
|
||||
// ============================================================================================================================
|
||||
func delete_beneficiary(stub shim.ChaincodeStubInterface, args []string) (pb.Response) {
|
||||
fmt.Println("starting delete_beneficiary")
|
||||
|
||||
if len(args) != 2 {
|
||||
return shim.Error("Incorrect number of arguments. Expecting 2")
|
||||
}
|
||||
|
||||
// input sanitation
|
||||
err := sanitize_arguments(args)
|
||||
if err != nil {
|
||||
return shim.Error(err.Error())
|
||||
}
|
||||
|
||||
id := args[0]
|
||||
authorized_by_association := args[1]
|
||||
|
||||
// get the beneficiary
|
||||
beneficiary, err := get_beneficiary(stub, id)
|
||||
if err != nil{
|
||||
fmt.Println("Failed to find beneficiary by id " + id)
|
||||
return shim.Error(err.Error())
|
||||
}
|
||||
|
||||
// check authorizing organisation
|
||||
if beneficiary.Owner.Association != authorized_by_association{
|
||||
return shim.Error("The association '" + authorized_by_association + "' cannot authorize deletion for '" + beneficiary.Owner.Association + "'.")
|
||||
}
|
||||
|
||||
// remove the beneficiary
|
||||
err = stub.DelState(id) //remove the key from chaincode state
|
||||
if err != nil {
|
||||
return shim.Error("Failed to delete state")
|
||||
}
|
||||
|
||||
fmt.Println("- end delete_beneficiary")
|
||||
return shim.Success(nil)
|
||||
}
|
||||
|
||||
|
||||
// ============================================================================================================================
|
||||
// Init Wallet - create a new wallet, store into chaincode state
|
||||
//
|
||||
// Shows off building a key's JSON value manually
|
||||
//
|
||||
// Inputs - Array of strings
|
||||
// 0 , 1 , 2 , 3
|
||||
// id , balance , owner id , authorization
|
||||
// ============================================================================================================================
|
||||
func init_wallet(stub shim.ChaincodeStubInterface, args []string) (pb.Response) {
|
||||
var err error
|
||||
fmt.Println("starting init_wallet")
|
||||
|
||||
if len(args) != 4 {
|
||||
return shim.Error("Incorrect number of arguments. Expecting 4")
|
||||
}
|
||||
|
||||
err = sanitize_arguments(args)
|
||||
if err != nil {
|
||||
return shim.Error(err.Error())
|
||||
}
|
||||
|
||||
id := args[0]
|
||||
owner_id := args[2]
|
||||
authorized_by_association := args[3]
|
||||
balance, err := strconv.Atoi(args[1])
|
||||
if err != nil {
|
||||
return shim.Error("Second argument must be a numeric string")
|
||||
}
|
||||
|
||||
//check if new owner exists
|
||||
owner, err := get_owner(stub, owner_id)
|
||||
if err != nil {
|
||||
fmt.Println("Failed to find owner - " + owner_id)
|
||||
return shim.Error(err.Error())
|
||||
}
|
||||
|
||||
//check authorizing organisation
|
||||
if owner.Association != authorized_by_association{
|
||||
return shim.Error("The association '" + authorized_by_association + "' cannot authorize creation for '" + owner.Association + "'.")
|
||||
}
|
||||
|
||||
//check if wallet id already exists
|
||||
wallet, err := get_wallet(stub, id)
|
||||
if err == nil {
|
||||
fmt.Println("This wallet already exists - " + id)
|
||||
fmt.Println(wallet)
|
||||
return shim.Error("This wallet already exists - " + id)
|
||||
}
|
||||
|
||||
//build the wallet json string manually
|
||||
str := `{
|
||||
"docType":"wallet",
|
||||
"id": "` + id + `",
|
||||
"balance": "` + balance + `",
|
||||
"owner": {
|
||||
"id": "` + owner_id + `",
|
||||
"name": "` + owner.Name + `",
|
||||
"firstname": "` + owner.Firstname + `"
|
||||
}
|
||||
}`
|
||||
err = stub.PutState(id, []byte(str)) //store wallet with id as key
|
||||
if err != nil {
|
||||
return shim.Error(err.Error())
|
||||
}
|
||||
|
||||
fmt.Println("- end init_wallet")
|
||||
return shim.Success(nil)
|
||||
}
|
||||
|
||||
|
||||
// ============================================================================================================================
|
||||
// Init Owner - create a new owner, store into chaincode state
|
||||
//
|
||||
// Shows off building key's value from GoLang Structure
|
||||
//
|
||||
// ============================================================================================================================
|
||||
func init_owner(stub shim.ChaincodeStubInterface, args []string) pb.Response {
|
||||
var err error
|
||||
fmt.Println("starting init_owner")
|
||||
|
||||
if len(args) != 9 {
|
||||
return shim.Error("Incorrect number of arguments. Expecting 9")
|
||||
}
|
||||
|
||||
err = sanitize_arguments(args)
|
||||
if err != nil {
|
||||
return shim.Error(err.Error())
|
||||
}
|
||||
|
||||
var owner Owner
|
||||
owner.ObjectType = "wallet_owner"
|
||||
owner.Id = args[0]
|
||||
owner.Name = strings.ToLower(args[1])
|
||||
owner.Firstname = strings.ToLower(args[2])
|
||||
owner.Mail = strings.ToLower(args[3])
|
||||
owner.Address = strings.ToLower(args[4])
|
||||
owner.City = strings.ToLower(args[5])
|
||||
owner.Password = strings.ToLower(args[7])
|
||||
owner.Association = args[8]
|
||||
owner.Enabled = true
|
||||
Postalcode, err := strconv.Atoi(args[6])
|
||||
if err != nil {
|
||||
return shim.Error("Seventh argument must be a numeric string")
|
||||
}
|
||||
|
||||
fmt.Println(owner)
|
||||
|
||||
//check if user already exists
|
||||
_, err = get_owner(stub, owner.Id)
|
||||
if err == nil {
|
||||
fmt.Println("This owner already exists - " + owner.Id)
|
||||
return shim.Error("This owner already exists - " + owner.Id)
|
||||
}
|
||||
|
||||
//store user
|
||||
ownerAsBytes, _ := json.Marshal(owner) //convert to array of bytes
|
||||
err = stub.PutState(owner.Id, ownerAsBytes) //store owner by its Id
|
||||
if err != nil {
|
||||
fmt.Println("Could not store user")
|
||||
return shim.Error(err.Error())
|
||||
}
|
||||
|
||||
fmt.Println("- end init_owner wallet")
|
||||
return shim.Success(nil)
|
||||
}
|
||||
|
||||
|
||||
// ============================================================================================================================
|
||||
// Init Beneficiary - create a new beneficiary, store into chaincode state
|
||||
//
|
||||
// Shows off building a key's JSON value manually
|
||||
//
|
||||
// Inputs - Array of strings
|
||||
// 0 , 1 , 2 , 3
|
||||
// id , balance , owner id , authorization
|
||||
// ============================================================================================================================
|
||||
func init_beneficiary(stub shim.ChaincodeStubInterface, args []string) (pb.Response) {
|
||||
var err error
|
||||
fmt.Println("starting init_beneficiary")
|
||||
|
||||
if len(args) != 6 {
|
||||
return shim.Error("Incorrect number of arguments. Expecting 6")
|
||||
}
|
||||
|
||||
err = sanitize_arguments(args)
|
||||
if err != nil {
|
||||
return shim.Error(err.Error())
|
||||
}
|
||||
|
||||
id := args[0]
|
||||
idBenef := args[1]
|
||||
nameBenef := strings.ToLower(args[2])
|
||||
firstnameBenef := strings.ToLower(args[3])
|
||||
owner_id := args[4]
|
||||
authorized_by_association := args[5]
|
||||
|
||||
//check if new owner exists
|
||||
owner, err := get_owner(stub, owner_id)
|
||||
if err != nil {
|
||||
fmt.Println("Failed to find owner - " + owner_id)
|
||||
return shim.Error(err.Error())
|
||||
}
|
||||
|
||||
//check authorizing organisation
|
||||
if owner.Association != authorized_by_association{
|
||||
return shim.Error("The association '" + authorized_by_association + "' cannot authorize creation for '" + owner.Association + "'.")
|
||||
}
|
||||
|
||||
//check if beneficiary id already exists
|
||||
beneficiary, err := get_beneficiary(stub, id)
|
||||
if err == nil {
|
||||
fmt.Println("This beneficiary already exists - " + id)
|
||||
fmt.Println(beneficiary)
|
||||
return shim.Error("This beneficiary already exists - " + id)
|
||||
}
|
||||
|
||||
//build the beneficiary json string manually
|
||||
str := `{
|
||||
"docType":"beneficiary",
|
||||
"id": "` + id + `",
|
||||
"idbenef": "` + idbenef + `",
|
||||
"namebenef": "` + namebenef + `",
|
||||
"firstnamebenef": "` + firstnamebenef + `",
|
||||
"owner": {
|
||||
"id": "` + owner_id + `",
|
||||
"name": "` + owner.Name + `",
|
||||
"firstname": "` + owner.Firstname + `"
|
||||
}
|
||||
}`
|
||||
err = stub.PutState(id, []byte(str)) //store beneficiary with id as key
|
||||
if err != nil {
|
||||
return shim.Error(err.Error())
|
||||
}
|
||||
|
||||
fmt.Println("- end init_beneficiary")
|
||||
return shim.Success(nil)
|
||||
}
|
||||
|
||||
|
||||
// ============================================================================================================================
|
||||
// Set Owner on Wallet
|
||||
//
|
||||
// Shows off GetState() and PutState()
|
||||
//
|
||||
// ============================================================================================================================
|
||||
func set_owner(stub shim.ChaincodeStubInterface, args []string) pb.Response {
|
||||
var err error
|
||||
fmt.Println("starting set_owner")
|
||||
|
||||
// this is quirky
|
||||
// todo - get the "association that authed the transfer" from the certificate instead of an argument
|
||||
// should be possible since we can now add attributes to the enrollment cert
|
||||
// as is.. this is a bit broken (security wise), but it's much much easier to demo! holding off for demos sake
|
||||
|
||||
if len(args) != 3 {
|
||||
return shim.Error("Incorrect number of arguments. Expecting 3")
|
||||
}
|
||||
|
||||
// input sanitation
|
||||
err = sanitize_arguments(args)
|
||||
if err != nil {
|
||||
return shim.Error(err.Error())
|
||||
}
|
||||
|
||||
var wallet_id = args[0]
|
||||
var new_owner_id = args[1]
|
||||
var authorized_by_association = args[2]
|
||||
fmt.Println(wallet_id + "->" + new_owner_id + " - |" + authorized_by_association)
|
||||
|
||||
// check if user already exists
|
||||
owner, err := get_owner(stub, new_owner_id)
|
||||
if err != nil {
|
||||
return shim.Error("This owner does not exist - " + new_owner_id)
|
||||
}
|
||||
|
||||
// get wallet's current state
|
||||
walletAsBytes, err := stub.GetState(wallet_id)
|
||||
if err != nil {
|
||||
return shim.Error("Failed to get wallet")
|
||||
}
|
||||
res := Wallet{}
|
||||
json.Unmarshal(walletAsBytes, &res)
|
||||
|
||||
// check authorizing association
|
||||
if res.Owner.Association != authorized_by_association{
|
||||
return shim.Error("The Association '" + authorized_by_association + "' cannot authorize transfers for '" + res.Owner.Association + "'.")
|
||||
}
|
||||
|
||||
// transfer the wallet
|
||||
res.Owner.Id = new_owner_id //change the owner
|
||||
res.Owner.Name = owner.Name
|
||||
res.Owner.Firstname = owner.Firstname
|
||||
res.Owner.Association = owner.Association
|
||||
jsonAsBytes, _ := json.Marshal(res) //convert to array of bytes
|
||||
err = stub.PutState(args[0], jsonAsBytes) //rewrite the wallet with id as key
|
||||
if err != nil {
|
||||
return shim.Error(err.Error())
|
||||
}
|
||||
|
||||
fmt.Println("- end set owner")
|
||||
return shim.Success(nil)
|
||||
}
|
||||
|
||||
|
||||
// ============================================================================================================================
|
||||
// Set Beneficiaries
|
||||
//
|
||||
// ============================================================================================================================
|
||||
func set_beneficiary(stub shim.ChaincodeStubInterface, args []string) pb.Response {
|
||||
var err error
|
||||
fmt.Println("starting set_beneficiary")
|
||||
|
||||
if len(args) != 3 {
|
||||
return shim.Error("Incorrect number of arguments. Expecting 3")
|
||||
}
|
||||
|
||||
// input sanitation
|
||||
err = sanitize_arguments(args)
|
||||
if err != nil {
|
||||
return shim.Error(err.Error())
|
||||
}
|
||||
|
||||
var beneficiary_id = args[0]
|
||||
var new_owner_id = args[1]
|
||||
var authorized_by_association = args[2]
|
||||
fmt.Println(beneficiary_id + "->" + new_owner_id + " - |" + authorized_by_association)
|
||||
|
||||
// check if user already exists
|
||||
owner, err := get_owner(stub, new_owner_id)
|
||||
if err != nil {
|
||||
return shim.Error("This owner does not exist - " + new_owner_id)
|
||||
}
|
||||
|
||||
// get beneficiary's current state
|
||||
beneficiaryAsBytes, err := stub.GetState(beneficiary_id)
|
||||
if err != nil {
|
||||
return shim.Error("Failed to get beneficiary")
|
||||
}
|
||||
res := Beneficiary{}
|
||||
json.Unmarshal(beneficiaryAsBytes, &res)
|
||||
|
||||
// check authorizing association
|
||||
if res.Owner.Association != authorized_by_association{
|
||||
return shim.Error("The Association '" + authorized_by_association + "' cannot authorize transfers for '" + res.Owner.Association + "'.")
|
||||
}
|
||||
|
||||
// transfer the beneficiary
|
||||
res.Owner.Id = new_owner_id //change the owner
|
||||
res.Owner.Name = owner.Name
|
||||
res.Owner.Firstname = owner.Firstname
|
||||
res.Owner.Association = owner.Association
|
||||
jsonAsBytes, _ := json.Marshal(res) //convert to array of bytes
|
||||
err = stub.PutState(args[0], jsonAsBytes) //rewrite the wallet with id as key
|
||||
if err != nil {
|
||||
return shim.Error(err.Error())
|
||||
}
|
||||
|
||||
fmt.Println("- end set owner")
|
||||
return shim.Success(nil)
|
||||
}
|
||||
|
||||
|
||||
// ============================================================================================================================
|
||||
// Disable Wallet Owner
|
||||
//
|
||||
// Shows off PutState()
|
||||
// ============================================================================================================================
|
||||
func disable_owner(stub shim.ChaincodeStubInterface, args []string) pb.Response {
|
||||
var err error
|
||||
fmt.Println("starting disable_owner")
|
||||
|
||||
if len(args) != 2 {
|
||||
return shim.Error("Incorrect number of arguments. Expecting 2")
|
||||
}
|
||||
|
||||
// input sanitation
|
||||
err = sanitize_arguments(args)
|
||||
if err != nil {
|
||||
return shim.Error(err.Error())
|
||||
}
|
||||
|
||||
var owner_id = args[0]
|
||||
var authorized_by_association = args[1]
|
||||
|
||||
// get the wallet owner data
|
||||
owner, err := get_owner(stub, owner_id)
|
||||
if err != nil {
|
||||
return shim.Error("This owner does not exist - " + owner_id)
|
||||
}
|
||||
|
||||
// check authorizing association
|
||||
if owner.Association != authorized_by_association {
|
||||
return shim.Error("The association '" + authorized_by_association + "' cannot change another association wallet owner")
|
||||
}
|
||||
|
||||
// disable the owner
|
||||
owner.Enabled = false
|
||||
jsonAsBytes, _ := json.Marshal(owner) //convert to array of bytes
|
||||
err = stub.PutState(args[0], jsonAsBytes) //rewrite the owner
|
||||
if err != nil {
|
||||
return shim.Error(err.Error())
|
||||
}
|
||||
|
||||
fmt.Println("- end disable_owner")
|
||||
return shim.Success(nil)
|
||||
}
|
||||
|
||||
|
||||
// ============================================================================================================================
|
||||
// Transfer X Money From a User to a Recipient
|
||||
//
|
||||
// ============================================================================================================================
|
||||
func transfer(stub shim.ChaincodeStubInterface, args []string) pb.Response {
|
||||
var err error
|
||||
fmt.Println("starting transfer")
|
||||
|
||||
if len(args) != 3 {
|
||||
return shim.Error("Incorrect number of arguments. Expecting 3")
|
||||
}
|
||||
|
||||
// input sanitation
|
||||
err = sanitize_arguments(args)
|
||||
if err != nil {
|
||||
return shim.Error(err.Error())
|
||||
}
|
||||
|
||||
id := args[0]
|
||||
dest_id := args[1]
|
||||
|
||||
// Get the state from the ledger
|
||||
// TODO: will be nice to have a GetAllState call to ledger
|
||||
Avalbytes, err := stub.GetState(id)
|
||||
if err != nil {
|
||||
return nil, errors.New("Failed to get state")
|
||||
}
|
||||
if Avalbytes == nil {
|
||||
return nil, errors.New("Entity not found")
|
||||
}
|
||||
Aval, _ = strconv.Atoi(string(Avalbytes))
|
||||
|
||||
Bvalbytes, err := stub.GetState(dest_id)
|
||||
if err != nil {
|
||||
return nil, errors.New("Failed to get state")
|
||||
}
|
||||
if Bvalbytes == nil {
|
||||
return nil, errors.New("Entity not found")
|
||||
}
|
||||
Bval, _ = strconv.Atoi(string(Bvalbytes))
|
||||
|
||||
// Perform the execution
|
||||
value, err = strconv.Atoi(args[2])
|
||||
Aval = Wallet.Balance - value
|
||||
Bval = Wallet.Balance + value
|
||||
fmt.Printf("Aval = %d, Bval = %d\n", Aval, Bval)
|
||||
|
||||
// Write the state back to the ledger
|
||||
err = stub.PutState(id, []byte(strconv.Itoa(Aval)))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = stub.PutState(dest_id, []byte(strconv.Itoa(Bval)))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
fmt.Println("- end transfer")
|
||||
return shim.Success(nil)
|
||||
}
|
50
develop/README.md
Normal file
50
develop/README.md
Normal file
|
@ -0,0 +1,50 @@
|
|||
3 tables au format json :
|
||||
|
||||
* Table Wallet
|
||||
_ID
|
||||
_Balance
|
||||
_Owner
|
||||
|
||||
* Table Owner
|
||||
_ID
|
||||
_Name
|
||||
_Firstname
|
||||
_Mail
|
||||
_Address
|
||||
_City
|
||||
_Postal Code
|
||||
_Password
|
||||
_Association
|
||||
_Enabled
|
||||
|
||||
* Table Beneficiary
|
||||
_Id
|
||||
_Name
|
||||
_Firstname
|
||||
_Owner
|
||||
|
||||
Un utilisateur peut avoir un ou plusieurs bénéficiaires et être bénéficiaire de 1 ou n personnes.
|
||||
Un wallet est rattaché à un et un seul utilisateur mais un utilisateur peut possèder n wallets.
|
||||
|
||||
|
||||
DEFINITION DES METHODES A APPELER :
|
||||
|
||||
function "Init" :
|
||||
* "init" : initialise l'état du chaincode et le reset
|
||||
function "Invoke" :
|
||||
* "read" : méthode pour tester un lecture sur le ledger
|
||||
* "write" : méthode pour tester une écriture sur le ledger
|
||||
* "init_wallet" : méthode pour créer une nouvelle entrée dans la table wallet
|
||||
* "init_owner" : méthode pour créer une nouvelle entrée dans la table owner
|
||||
* "init_beneficiary" : méthode pour créer un nouveau bénéficiaire rattaché à un utilisateur
|
||||
* "delete_wallet" : méthode pour supprimer un portefeuille
|
||||
* "delete_owner" : méthode pour supprimer un utilisateur
|
||||
* "delete_beneficiary" : méthode pour supprimer un utilisateur d'un bénéficiaire
|
||||
* "set_owner" : méthode pour changer le propriétaire d'un wallet
|
||||
* "set_beneficiary" : méthode pour changer un utilisateur dans la liste des bénéficiaires
|
||||
* "disable_owner" : méthode pour désactiver le propriétaire d'un wallet pour ne plus l'afficher via un GET
|
||||
* "transfer" : méthode pour effectuer une transaction
|
||||
* "get_wallet" : méthode pour afficher un wallet
|
||||
* "get_owner" : méthode pour afficher un utilisateur
|
||||
* "get_beneficiary" : méthode pour afficher un bénéficiaire
|
||||
* "get_transaction" : méthode pour afficher une transaction
|
|
@ -1,200 +0,0 @@
|
|||
/*
|
||||
Copyright IBM Corp. 2016 All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
//WARNING - this chaincode's ID is hard-coded in chaincode_example04 to illustrate one way of
|
||||
//calling chaincode from a chaincode. If this example is modified, chaincode_example04.go has
|
||||
//to be modified as well with the new ID of chaincode_example02.
|
||||
//chaincode_example05 show's how chaincode ID can be passed in as a parameter instead of
|
||||
//hard-coding.
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
|
||||
"github.com/hyperledger/fabric/core/chaincode/shim"
|
||||
pb "github.com/hyperledger/fabric/protos/peer"
|
||||
)
|
||||
|
||||
|
||||
// SimpleChaincode example simple Chaincode implementation
|
||||
type SimpleChaincode struct {
|
||||
}
|
||||
|
||||
type owner struct {
|
||||
ObjectType string `json:"docType"`
|
||||
UserId string `json:"userId"`
|
||||
UserName string `json:"userName"`
|
||||
UserFirstName string `json:"userFirstName"`
|
||||
UserPhone string `json:"userPhone"`
|
||||
UserAssociation string `json:"userAssociation"`
|
||||
UserAuthorized bool `json:"userAuthorized"`
|
||||
}
|
||||
|
||||
|
||||
type wallet struct {
|
||||
ObjectType string `json:"docType"` //docType is used to distinguish the various type$
|
||||
Id string `json:"id"` //the fieldtags are needed to keep case from bounci$
|
||||
WalletType string `json:"walletType"`
|
||||
Balance float64 `json:"balance"`
|
||||
Owner string `json:"owner"`
|
||||
}
|
||||
|
||||
|
||||
func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface) pb.Response {
|
||||
fmt.Println("monnethic Init")
|
||||
return shim.Success(nil)
|
||||
}
|
||||
|
||||
|
||||
func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
|
||||
fmt.Println("ex02 Invoke")
|
||||
function, args := stub.GetFunctionAndParameters()
|
||||
/* if function == "invoke" {
|
||||
// Make payment of X units from A to B
|
||||
return t.invoke(stub, args)
|
||||
} else if function == "delete" {
|
||||
// Deletes an entity from its state
|
||||
return t.delete(stub, args)
|
||||
} else if function == "query" {
|
||||
// the old "Query" is now implemtned in invoke
|
||||
return t.query(stub, args)
|
||||
} else if function == "register" {
|
||||
// register a new user into the ledger
|
||||
return t.register(stub, args)
|
||||
} else*/ if function == "registerUser" {
|
||||
// initiate a new account
|
||||
return t.registerUser(stub, args)
|
||||
} else if function == "readUser" {
|
||||
// query a specific user from the ledger
|
||||
return t.readUser(stub, args)
|
||||
} else if function == "deleteUser" {
|
||||
// delete a specific user from the ledger
|
||||
return t.deleteUser(stub, args)
|
||||
} else if function == "setUserPermission" {
|
||||
// change the permission of an account
|
||||
return t.setUserPermission(stub, args)
|
||||
} else if function == "initWallet" {
|
||||
// initiate a new wallet
|
||||
return t.initWallet(stub, args)
|
||||
} else if function == "readWallet" {
|
||||
// query a specific wallet from the ledger
|
||||
return t.readWallet(stub, args)
|
||||
} else if function == "deleteWallet" {
|
||||
// delete a specific wallet from the ledger
|
||||
return t.deleteWallet(stub, args)
|
||||
} else if function == "transferWallet" {
|
||||
// change the owner of a specific wallet
|
||||
return t.transferWallet(stub, args)
|
||||
} else if function == "setBalanceOnWallet" {
|
||||
// set a new balance to a wallet
|
||||
return t.setBalanceOnWallet(stub, args)
|
||||
} else if function == "transaction" {
|
||||
// make a transaction of X units from a wallet to an other
|
||||
return t.transaction(stub, args)
|
||||
} else if function == "queryWalletsByOwner" {
|
||||
// get all wallets of a user by querying his specific account
|
||||
return t.queryWalletsByOwner(stub, args)
|
||||
} else if function == "queryWalletsByType" {
|
||||
// get all wallets of a specific wallet type by querying a specific type
|
||||
return t.queryWalletsByType(stub, args)
|
||||
} else if function == "queryWallets" {
|
||||
// get a specific wallet
|
||||
return t.queryWallets(stub, args)
|
||||
} else if function == "getHistoryForWallet" {
|
||||
// query the full state history of a wallet
|
||||
return t.getHistoryForWallet(stub, args)
|
||||
} else if function == "getAllEntities" {
|
||||
// get All Entities of the present ledger
|
||||
return t.getAllEntities(stub, args)
|
||||
}
|
||||
|
||||
return shim.Error("Invalid invoke function name. Expecting \"invoke\" \"delete\" \"query\" \"register\"")
|
||||
}
|
||||
|
||||
|
||||
func main() {
|
||||
err := shim.Start(new(SimpleChaincode))
|
||||
if err != nil {
|
||||
fmt.Printf("Error starting Simple chaincode: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ===========================================================================================
|
||||
// constructQueryResponseFromIterator constructs a JSON array containing query results from
|
||||
// a given result iterator
|
||||
// ===========================================================================================
|
||||
func constructQueryResponseFromIterator(resultsIterator shim.StateQueryIteratorInterface) (*bytes.Buffer, error) {
|
||||
|
||||
// buffer is a JSON array containing QueryResults
|
||||
var buffer bytes.Buffer
|
||||
buffer.WriteString("[")
|
||||
|
||||
bArrayMemberAlreadyWritten := false
|
||||
for resultsIterator.HasNext() {
|
||||
queryResponse, err := resultsIterator.Next()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Add a comma before array members, suppress it for the first array member
|
||||
if bArrayMemberAlreadyWritten == true {
|
||||
buffer.WriteString(",")
|
||||
}
|
||||
|
||||
buffer.WriteString("{\"Key\":")
|
||||
buffer.WriteString("\"")
|
||||
buffer.WriteString(queryResponse.Key)
|
||||
buffer.WriteString("\"")
|
||||
|
||||
buffer.WriteString(", \"Record\":")
|
||||
|
||||
// Record is a JSON object, so we write as-is
|
||||
buffer.WriteString(string(queryResponse.Value))
|
||||
buffer.WriteString("}")
|
||||
bArrayMemberAlreadyWritten = true
|
||||
}
|
||||
buffer.WriteString("]")
|
||||
|
||||
return &buffer, nil
|
||||
}
|
||||
|
||||
|
||||
// =========================================================================================
|
||||
// getQueryResultForQueryString executes the passed in query string.
|
||||
// Result set is built and returned as a byte array containing the JSON results.
|
||||
// =========================================================================================
|
||||
func getQueryResultForQueryString(stub shim.ChaincodeStubInterface, queryString string) ([]byte, error) {
|
||||
|
||||
fmt.Printf("- getQueryResultForQueryString queryString:\n%s\n", queryString)
|
||||
|
||||
resultsIterator, err := stub.GetQueryResult(queryString)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resultsIterator.Close()
|
||||
|
||||
buffer, err := constructQueryResponseFromIterator(resultsIterator)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
fmt.Printf("- getQueryResultForQueryString queryResult:\n%s\n", buffer.String())
|
||||
|
||||
return buffer.Bytes(), nil
|
||||
}
|
|
@ -1,724 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/hyperledger/fabric/core/chaincode/shim"
|
||||
pb "github.com/hyperledger/fabric/protos/peer"
|
||||
)
|
||||
|
||||
|
||||
func (t *SimpleChaincode) registerUser(stub shim.ChaincodeStubInterface, args []string) pb.Response {
|
||||
|
||||
var err error
|
||||
|
||||
if len(args) != 5 {
|
||||
return shim.Error("Incorrect number of arguments. Expecting 6")
|
||||
}
|
||||
|
||||
// ==== Input sanitation ====
|
||||
fmt.Println("- start init user")
|
||||
if len(args[0]) <= 0 {
|
||||
return shim.Error("1st argument must be a non-empty string")
|
||||
}
|
||||
if len(args[1]) <= 0 {
|
||||
return shim.Error("2nd argument must be a non-empty string")
|
||||
}
|
||||
if len(args[2]) <= 0 {
|
||||
return shim.Error("3rd argument must be a non-empty string")
|
||||
}
|
||||
if len(args[3]) <= 0 {
|
||||
return shim.Error("4th argument must be a non-empty string")
|
||||
}
|
||||
if len(args[4]) <= 0 {
|
||||
return shim.Error("5th argument must be a non-empty string")
|
||||
}
|
||||
|
||||
|
||||
userId := args[0]
|
||||
userName := strings.ToLower(args[1])
|
||||
userFirstName := strings.ToLower(args[2])
|
||||
userPhone := strings.ToLower(args[3])
|
||||
userAssociation := strings.ToLower(args[4])
|
||||
userAuthorized := false
|
||||
|
||||
if err != nil {
|
||||
return shim.Error("3rd argument must be a numeric string")
|
||||
}
|
||||
|
||||
// ==== Check if user already exists ====
|
||||
ownerAsBytes, err := stub.GetState(userId)
|
||||
if err != nil {
|
||||
return shim.Error("Failed to get user: " + err.Error())
|
||||
} else if ownerAsBytes != nil {
|
||||
fmt.Println("This user already exists: " + userId)
|
||||
return shim.Error("This user already exists: " + userId)
|
||||
}
|
||||
|
||||
// ==== Create wallet object and marshal to JSON ====
|
||||
objectType := "owner"
|
||||
owner := &owner{objectType, userId, userName, userFirstName, userPhone, userAssociation, userAuthorized}
|
||||
ownerJSONasBytes, err := json.Marshal(owner)
|
||||
if err != nil {
|
||||
return shim.Error(err.Error())
|
||||
}
|
||||
//Alternatively, build the marble json string manually if you don't want to us$
|
||||
//walletJSONasString := `{"docType":"Wallet", "id": "` + "walletType + `", "s$
|
||||
//walletJSONasBytes := []byte(str)
|
||||
|
||||
// === Save user to state ===
|
||||
err = stub.PutState(userId, ownerJSONasBytes)
|
||||
if err != nil {
|
||||
return shim.Error(err.Error())
|
||||
}
|
||||
|
||||
// ==== Index the wallet to enable type-based range queries, e.g. return all $
|
||||
// An 'index' is a normal key/value entry in state.
|
||||
// The key is a composite key, with the elements that you want to range query$
|
||||
// In our case, the composite key is based on indexName~typeWallet~id.
|
||||
// This will enable very efficient state range queries based on composite key$
|
||||
indexName := "userAssociation~userId"
|
||||
ownerAssociationIdIndexKey, err := stub.CreateCompositeKey(indexName, []string{owner.UserAssociation, owner.UserId})
|
||||
if err != nil {
|
||||
return shim.Error(err.Error())
|
||||
}
|
||||
// Save index entry to state. Only the key name is needed, no need to store a$
|
||||
// Note - passing a 'nil' value will effectively delete the key from state, t$
|
||||
value := []byte{0x00}
|
||||
stub.PutState(ownerAssociationIdIndexKey, value)
|
||||
|
||||
// ==== User saved and indexed. Return success ====
|
||||
fmt.Println("- end init user")
|
||||
return shim.Success(nil)
|
||||
}
|
||||
|
||||
|
||||
//===============================================
|
||||
// readUser - read a user from chaincode state
|
||||
//===============================================
|
||||
func (t *SimpleChaincode) readUser(stub shim.ChaincodeStubInterface, args []string) pb.Response {
|
||||
var userId, jsonResp string
|
||||
var err error
|
||||
|
||||
if len(args) != 1 {
|
||||
return shim.Error("Incorrect number of arguments. Expecting name of the user to query")
|
||||
}
|
||||
|
||||
userId = args[0]
|
||||
valAsbytes, err := stub.GetState(userId) //get the wallet from chaincode state
|
||||
if err != nil {
|
||||
jsonResp = "{\"Error\":\"Failed to get state for " + userId + "\"}"
|
||||
return shim.Error(jsonResp)
|
||||
} else if valAsbytes == nil {
|
||||
jsonResp = "{\"Error\":\"Wallet does not exist: " + userId + "\"}"
|
||||
return shim.Error(jsonResp)
|
||||
}
|
||||
|
||||
return shim.Success(valAsbytes)
|
||||
}
|
||||
|
||||
|
||||
// ==================================================
|
||||
// delete - remove a wallet key/value pair from state
|
||||
// ==================================================
|
||||
func (t *SimpleChaincode) deleteUser(stub shim.ChaincodeStubInterface, args []string) pb.Response {
|
||||
var jsonResp string
|
||||
var ownerJSON owner
|
||||
if len(args) != 1 {
|
||||
return shim.Error("Incorrect number of arguments. Expecting 1")
|
||||
}
|
||||
|
||||
userId := args[0]
|
||||
|
||||
// to maintain the color~name index, we need to read the marble first and get its color
|
||||
valAsbytes, err := stub.GetState(userId) //get the marble from chaincode state
|
||||
if err != nil {
|
||||
jsonResp = "{\"Error\":\"Failed to get state for " + userId + "\"}"
|
||||
return shim.Error(jsonResp)
|
||||
} else if valAsbytes == nil {
|
||||
jsonResp = "{\"Error\":\"User does not exist: " + userId + "\"}"
|
||||
return shim.Error(jsonResp)
|
||||
}
|
||||
|
||||
err = json.Unmarshal([]byte(valAsbytes), &ownerJSON)
|
||||
|
||||
if err != nil {
|
||||
jsonResp = "{\"Error\":\"Failed to get state for " + userId + "\"}"
|
||||
return shim.Error(jsonResp)
|
||||
} else if valAsbytes == nil {
|
||||
jsonResp = "{\"Error\":\"User does not exist: " + userId + "\"}"
|
||||
return shim.Error(jsonResp)
|
||||
}
|
||||
|
||||
err = json.Unmarshal([]byte(valAsbytes), &ownerJSON)
|
||||
if err != nil {
|
||||
jsonResp = "{\"Error\":\"Failed to decode JSON of: " + userId + "\"}"
|
||||
return shim.Error(jsonResp)
|
||||
}
|
||||
|
||||
err = stub.DelState(userId) //remove the owner from chaincode state
|
||||
if err != nil {
|
||||
return shim.Error("Failed to delete state:" + err.Error())
|
||||
}
|
||||
|
||||
// maintain the index
|
||||
indexName := "userAssociation~userId"
|
||||
ownerAssociationIdIndexKey, err := stub.CreateCompositeKey(indexName, []string{ownerJSON.UserAssociation, ownerJSON.UserId})
|
||||
if err != nil {
|
||||
return shim.Error(err.Error())
|
||||
}
|
||||
|
||||
// Delete index entry to state.
|
||||
err = stub.DelState(ownerAssociationIdIndexKey)
|
||||
if err != nil {
|
||||
return shim.Error("Failed to delete state:" + err.Error())
|
||||
}
|
||||
return shim.Success(nil)
|
||||
}
|
||||
|
||||
|
||||
// ===========================================================
|
||||
// set a permission of an account by setting authorization to create a wallet
|
||||
// ===========================================================
|
||||
func (t *SimpleChaincode) setUserPermission(stub shim.ChaincodeStubInterface, args []string) pb.Response {
|
||||
|
||||
// 0 1
|
||||
// "name", "bob"
|
||||
if len(args) < 1 {
|
||||
return shim.Error("Incorrect number of arguments. Expecting 2")
|
||||
}
|
||||
|
||||
userId := args[0]
|
||||
|
||||
fmt.Println("- start setUserPermission ", userId)
|
||||
|
||||
// ==== Check if user already exists ====
|
||||
ownerAsBytes, err := stub.GetState(userId)
|
||||
if err != nil {
|
||||
return shim.Error("Failed to get user: " + err.Error())
|
||||
} else if ownerAsBytes == nil {
|
||||
fmt.Println("This wallet doesn't exists: " + userId)
|
||||
return shim.Error("This wallet doesn't exists: " + userId)
|
||||
}
|
||||
|
||||
ownerToSet := owner{}
|
||||
err = json.Unmarshal(ownerAsBytes, &ownerToSet) //unmarshal it aka JSON
|
||||
if err != nil {
|
||||
return shim.Error(err.Error())
|
||||
}
|
||||
|
||||
//if walletToSet.Owner
|
||||
ownerToSet.UserAuthorized = true //change the permission
|
||||
|
||||
ownerJSONasBytes, _ := json.Marshal(ownerToSet)
|
||||
err = stub.PutState(userId, ownerJSONasBytes) //rewrite the wallet
|
||||
if err != nil {
|
||||
return shim.Error(err.Error())
|
||||
}
|
||||
fmt.Println("- end setUserPermission (success)")
|
||||
return shim.Success(nil)
|
||||
}
|
||||
|
||||
|
||||
func (t *SimpleChaincode) initWallet(stub shim.ChaincodeStubInterface, args []string) pb.Response {
|
||||
var err error
|
||||
|
||||
if len(args) != 3 {
|
||||
return shim.Error("Incorrect number of arguments. Expecting 4")
|
||||
}
|
||||
|
||||
// ==== Input sanitation ====
|
||||
fmt.Println("- start init wallet")
|
||||
if len(args[0]) <= 0 {
|
||||
return shim.Error("1st argument must be a non-empty string")
|
||||
}
|
||||
if len(args[1]) <= 0 {
|
||||
return shim.Error("2nd argument must be a non-empty string")
|
||||
}
|
||||
if len(args[2]) <= 0 {
|
||||
return shim.Error("3rd argument must be a non-empty string")
|
||||
}
|
||||
|
||||
walletId := args[0]
|
||||
walletType := strings.ToLower(args[1])
|
||||
owner := args[2]
|
||||
balance := 0.0
|
||||
|
||||
if err != nil {
|
||||
return shim.Error("3rd argument must be a numeric string")
|
||||
}
|
||||
|
||||
// ==== Check if user already exists ====
|
||||
ownerAsBytes, err := stub.GetState(owner)
|
||||
if err != nil {
|
||||
return shim.Error("Failed to get owner: " + err.Error())
|
||||
} else if ownerAsBytes == nil {
|
||||
fmt.Println("This user doesn't exists: " + owner)
|
||||
return shim.Error("This user doesn't exists: " + owner)
|
||||
}
|
||||
|
||||
// ==== Check if wallet already exists ====
|
||||
walletAsBytes, err := stub.GetState(walletId)
|
||||
if err != nil {
|
||||
return shim.Error("Failed to get wallet: " + err.Error())
|
||||
} else if walletAsBytes != nil {
|
||||
fmt.Println("This wallet already exists: " + walletId)
|
||||
return shim.Error("This wallet already exists: " + walletId)
|
||||
}
|
||||
|
||||
// ==== Create wallet object and marshal to JSON ====
|
||||
objectType := "wallet"
|
||||
wallet := &wallet{objectType, walletId, walletType, balance, owner}
|
||||
walletJSONasBytes, err := json.Marshal(wallet)
|
||||
if err != nil {
|
||||
return shim.Error(err.Error())
|
||||
}
|
||||
|
||||
//Alternatively, build the marble json string manually if you don't want to use struct marshalling
|
||||
//walletJSONasString := `{"docType":"Wallet", "id": "` + "walletType + `", "sold": `, strconv.Itoa(size) , `"owner": "` + owner + `"}`
|
||||
//walletJSONasBytes := []byte(str)
|
||||
|
||||
|
||||
// === Save wallet to state ===
|
||||
err = stub.PutState(walletId, walletJSONasBytes)
|
||||
if err != nil {
|
||||
return shim.Error(err.Error())
|
||||
}
|
||||
|
||||
// ==== Index the wallet to enable type-based range queries, e.g. return all clients wallets ====
|
||||
// An 'index' is a normal key/value entry in state.
|
||||
// The key is a composite key, with the elements that you want to range query on listed first.
|
||||
// In our case, the composite key is based on indexName~typeWallet~id.
|
||||
// This will enable very efficient state range queries based on composite keys matching indexName~type~*
|
||||
indexName := "typeWallet~id"
|
||||
walletTypeNameIndexKey, err := stub.CreateCompositeKey(indexName, []string{wallet.WalletType, wallet.Id})
|
||||
if err != nil {
|
||||
return shim.Error(err.Error())
|
||||
}
|
||||
|
||||
// Save index entry to state. Only the key name is needed, no need to store a duplicate copy of the marble.
|
||||
// Note - passing a 'nil' value will effectively delete the key from state, therefore we pass null character as value
|
||||
value := []byte{0x00}
|
||||
stub.PutState(walletTypeNameIndexKey, value)
|
||||
|
||||
|
||||
// ==== Wallet saved and indexed. Return success ====
|
||||
fmt.Println("- end init wallet")
|
||||
return shim.Success(nil)
|
||||
}
|
||||
|
||||
|
||||
// ===============================================
|
||||
// readWallet - read a wallet from chaincode state
|
||||
// ===============================================
|
||||
func (t *SimpleChaincode) readWallet(stub shim.ChaincodeStubInterface, args []string) pb.Response {
|
||||
|
||||
var id, jsonResp string
|
||||
var err error
|
||||
|
||||
if len(args) != 1 {
|
||||
return shim.Error("Incorrect number of arguments. Expecting name of the wallet to query")
|
||||
}
|
||||
|
||||
id = args[0]
|
||||
valAsbytes, err := stub.GetState(id) //get the wallet from chaincode state
|
||||
if err != nil {
|
||||
jsonResp = "{\"Error\":\"Failed to get state for " + id + "\"}"
|
||||
return shim.Error(jsonResp)
|
||||
} else if valAsbytes == nil {
|
||||
jsonResp = "{\"Error\":\"Wallet does not exist: " + id + "\"}"
|
||||
return shim.Error(jsonResp)
|
||||
}
|
||||
|
||||
return shim.Success(valAsbytes)
|
||||
}
|
||||
|
||||
|
||||
// ==================================================
|
||||
// delete - remove a wallet key/value pair from state
|
||||
// ==================================================
|
||||
func (t *SimpleChaincode) deleteWallet(stub shim.ChaincodeStubInterface, args []string) pb.Response {
|
||||
|
||||
var jsonResp string
|
||||
var walletJSON wallet
|
||||
if len(args) != 1 {
|
||||
return shim.Error("Incorrect number of arguments. Expecting 1")
|
||||
}
|
||||
|
||||
Id := args[0]
|
||||
|
||||
// to maintain the color~name index, we need to read the marble first and get its color
|
||||
valAsbytes, err := stub.GetState(Id) //get the marble from chaincode state
|
||||
if err != nil {
|
||||
jsonResp = "{\"Error\":\"Failed to get state for " + Id + "\"}"
|
||||
return shim.Error(jsonResp)
|
||||
} else if valAsbytes == nil {
|
||||
jsonResp = "{\"Error\":\"Wallet does not exist: " + Id + "\"}"
|
||||
return shim.Error(jsonResp)
|
||||
}
|
||||
|
||||
err = json.Unmarshal([]byte(valAsbytes), &walletJSON)
|
||||
|
||||
if err != nil {
|
||||
jsonResp = "{\"Error\":\"Failed to get state for " + Id + "\"}"
|
||||
return shim.Error(jsonResp)
|
||||
} else if valAsbytes == nil {
|
||||
jsonResp = "{\"Error\":\"Wallet does not exist: " + Id + "\"}"
|
||||
return shim.Error(jsonResp)
|
||||
}
|
||||
|
||||
err = json.Unmarshal([]byte(valAsbytes), &walletJSON)
|
||||
if err != nil {
|
||||
jsonResp = "{\"Error\":\"Failed to decode JSON of: " + Id + "\"}"
|
||||
return shim.Error(jsonResp)
|
||||
}
|
||||
|
||||
err = stub.DelState(Id) //remove the wallet from chaincode state
|
||||
if err != nil {
|
||||
return shim.Error("Failed to delete state:" + err.Error())
|
||||
}
|
||||
|
||||
// maintain the index
|
||||
indexName := "typeWallet~id"
|
||||
walletTypeNameIndexKey, err := stub.CreateCompositeKey(indexName, []string{walletJSON.WalletType, walletJSON.Id})
|
||||
if err != nil {
|
||||
return shim.Error(err.Error())
|
||||
}
|
||||
|
||||
// Delete index entry to state.
|
||||
err = stub.DelState(walletTypeNameIndexKey)
|
||||
if err != nil {
|
||||
return shim.Error("Failed to delete state:" + err.Error())
|
||||
}
|
||||
|
||||
return shim.Success(nil)
|
||||
}
|
||||
|
||||
|
||||
// ===========================================================
|
||||
// transfer a wallet by setting a new owner name on the wallet
|
||||
// ===========================================================
|
||||
func (t *SimpleChaincode) transferWallet(stub shim.ChaincodeStubInterface, args []string) pb.Response {
|
||||
|
||||
if len(args) < 2 {
|
||||
return shim.Error("Incorrect number of arguments. Expecting 2")
|
||||
}
|
||||
|
||||
walletId := args[0]
|
||||
newOwner := args[1]
|
||||
fmt.Println("- start transferWallet ", walletId, newOwner)
|
||||
|
||||
// ==== Check if user already exists ====
|
||||
ownerAsBytes, err := stub.GetState(newOwner)
|
||||
if err != nil {
|
||||
return shim.Error("Failed to get user: " + err.Error())
|
||||
} else if ownerAsBytes == nil {
|
||||
fmt.Println("This user doesn't exists: " + newOwner)
|
||||
return shim.Error("This user doesn't exists: " + newOwner)
|
||||
}
|
||||
|
||||
walletAsBytes, err := stub.GetState(walletId)
|
||||
|
||||
if err != nil {
|
||||
return shim.Error("Failed to get wallet:" + err.Error())
|
||||
} else if walletAsBytes == nil {
|
||||
return shim.Error("wallet does not exist")
|
||||
}
|
||||
|
||||
walletToTransfer := wallet{}
|
||||
err = json.Unmarshal(walletAsBytes, &walletToTransfer) //unmarshal it aka JSON
|
||||
if err != nil {
|
||||
return shim.Error(err.Error())
|
||||
}
|
||||
walletToTransfer.Owner = newOwner //change the owner
|
||||
|
||||
walletJSONasBytes, _ := json.Marshal(walletToTransfer)
|
||||
err = stub.PutState(walletId, walletJSONasBytes) //rewrite the wallet
|
||||
if err != nil {
|
||||
return shim.Error(err.Error())
|
||||
}
|
||||
|
||||
fmt.Println("- end transferWallet (success)")
|
||||
return shim.Success(nil)
|
||||
}
|
||||
|
||||
|
||||
// ===========================================================
|
||||
// set a sold of a wallet by setting a new owner name on the wallet
|
||||
// ===========================================================
|
||||
func (t *SimpleChaincode) setBalanceOnWallet(stub shim.ChaincodeStubInterface, args []string) pb.Response {
|
||||
|
||||
if len(args) < 2 {
|
||||
return shim.Error("Incorrect number of arguments. Expecting 2")
|
||||
}
|
||||
|
||||
walletId := args[0]
|
||||
newBalance, err := strconv.ParseFloat(args[1], 64)
|
||||
fmt.Println("- start setBalanceOnWallet ", walletId, newBalance)
|
||||
|
||||
// ==== Check if wallet already exists ====
|
||||
walletAsBytes, err := stub.GetState(walletId)
|
||||
if err != nil {
|
||||
return shim.Error("Failed to get wallet: " + err.Error())
|
||||
} else if walletAsBytes == nil {
|
||||
fmt.Println("This wallet doesn't exists: " + walletId)
|
||||
return shim.Error("This wallet doesn't exists: " + walletId)
|
||||
}
|
||||
|
||||
walletToSet := wallet{}
|
||||
err = json.Unmarshal(walletAsBytes, &walletToSet) //unmarshal it aka JSON
|
||||
if err != nil {
|
||||
return shim.Error(err.Error())
|
||||
}
|
||||
|
||||
//if walletToSet.Owner
|
||||
walletToSet.Balance = walletToSet.Balance + newBalance //change the balance
|
||||
|
||||
walletJSONasBytes, _ := json.Marshal(walletToSet)
|
||||
err = stub.PutState(walletId, walletJSONasBytes) //rewrite the wallet
|
||||
if err != nil {
|
||||
return shim.Error(err.Error())
|
||||
}
|
||||
|
||||
fmt.Println("- end setBalanceOnWallet (success)")
|
||||
return shim.Success(nil)
|
||||
}
|
||||
|
||||
|
||||
// Transaction makes payment of X units from A to B
|
||||
func (t *SimpleChaincode) transaction(stub shim.ChaincodeStubInterface, args []string) pb.Response {
|
||||
|
||||
if len(args) != 3 {
|
||||
return shim.Error("Incorrect number of arguments. Expecting 3")
|
||||
}
|
||||
|
||||
walletId := args[0]
|
||||
walletTargetId := args[1]
|
||||
transactionValue, err := strconv.ParseFloat(args[2], 64)
|
||||
|
||||
fmt.Println("- start transaction ", walletId, transactionValue)
|
||||
|
||||
// ==== Check if wallet already exists ====
|
||||
walletAsBytes, err := stub.GetState(walletId)
|
||||
if err != nil {
|
||||
return shim.Error("Failed to get wallet: " + err.Error())
|
||||
} else if walletAsBytes == nil {
|
||||
fmt.Println("This wallet doesn't exists: " + walletId)
|
||||
return shim.Error("This wallet doesn't exists: " + walletId)
|
||||
}
|
||||
|
||||
// ==== Check if wallet already exists ====
|
||||
walletTargetAsBytes, err := stub.GetState(walletTargetId)
|
||||
if err != nil {
|
||||
return shim.Error("Failed to get wallet: " + err.Error())
|
||||
} else if walletTargetAsBytes == nil {
|
||||
fmt.Println("This wallet doesn't exists: " + walletTargetId)
|
||||
return shim.Error("This wallet doesn't exists: " + walletTargetId)
|
||||
}
|
||||
|
||||
walletBalanceToSet := wallet{}
|
||||
err = json.Unmarshal(walletAsBytes, &walletBalanceToSet) //unmarshal it aka JSON
|
||||
if err != nil {
|
||||
return shim.Error(err.Error())
|
||||
}
|
||||
|
||||
if walletBalanceToSet.Balance <= 0 {
|
||||
return shim.Error("This wallet is not allowed to make a transaction:" + walletId)
|
||||
} else {
|
||||
walletBalanceToSet.Balance = walletBalanceToSet.Balance - transactionValue //change the balance
|
||||
}
|
||||
|
||||
walletJSONasBytes, _ := json.Marshal(walletBalanceToSet)
|
||||
err = stub.PutState(walletId, walletJSONasBytes) //rewrite the wallet
|
||||
if err != nil {
|
||||
return shim.Error(err.Error())
|
||||
}
|
||||
|
||||
walletTargetBalanceToSet := wallet{}
|
||||
err = json.Unmarshal(walletTargetAsBytes, &walletTargetBalanceToSet) //unmarshal it aka JSON
|
||||
if err != nil {
|
||||
return shim.Error(err.Error())
|
||||
}
|
||||
|
||||
walletTargetBalanceToSet.Balance = walletTargetBalanceToSet.Balance + transactionValue
|
||||
|
||||
walletTargetJSONasBytes, _ := json.Marshal(walletTargetBalanceToSet)
|
||||
err = stub.PutState(walletTargetId, walletTargetJSONasBytes) //rewrite the wallet
|
||||
if err != nil {
|
||||
return shim.Error(err.Error())
|
||||
}
|
||||
|
||||
fmt.Println("- end setBalanceOnWallet (success)")
|
||||
return shim.Success(nil)
|
||||
}
|
||||
|
||||
|
||||
func (t *SimpleChaincode) queryWalletsByOwner(stub shim.ChaincodeStubInterface, args []string) pb.Response {
|
||||
|
||||
if len(args) < 1 {
|
||||
return shim.Error("Incorrect number of arguments. Expecting 1")
|
||||
}
|
||||
|
||||
owner := args[0]
|
||||
|
||||
queryString := fmt.Sprintf("{\"selector\":{\"docType\":\"wallet\",\"owner\":\"%s\"}}", owner)
|
||||
|
||||
queryResults, err := getQueryResultForQueryString(stub, queryString)
|
||||
if err != nil {
|
||||
return shim.Error(err.Error())
|
||||
}
|
||||
|
||||
return shim.Success(queryResults)
|
||||
}
|
||||
|
||||
|
||||
func (t *SimpleChaincode) queryWalletsByType(stub shim.ChaincodeStubInterface, args []string) pb.Response {
|
||||
|
||||
if len(args) < 1 {
|
||||
return shim.Error("Incorrect number of arguments. Expecting 1")
|
||||
}
|
||||
|
||||
walletType := strings.ToLower(args[0])
|
||||
|
||||
queryString := fmt.Sprintf("{\"selector\":{\"docType\":\"wallet\",\"walletType\":\"%s\"}}", walletType)
|
||||
|
||||
queryResults, err := getQueryResultForQueryString(stub, queryString)
|
||||
if err != nil {
|
||||
return shim.Error(err.Error())
|
||||
}
|
||||
|
||||
return shim.Success(queryResults)
|
||||
}
|
||||
|
||||
|
||||
// ===== Example: Ad hoc rich query ========================================================
|
||||
// queryMarbles uses a query string to perform a query for marbles.
|
||||
// Query string matching state database syntax is passed in and executed as is.
|
||||
// Supports ad hoc queries that can be defined at runtime by the client.
|
||||
// If this is not desired, follow the queryMarblesForOwner example for parameterized queries.
|
||||
// Only available on state databases that support rich query (e.g. CouchDB)
|
||||
// =========================================================================================
|
||||
func (t *SimpleChaincode) queryWallets(stub shim.ChaincodeStubInterface, args []string) pb.Response {
|
||||
|
||||
// "queryString"
|
||||
if len(args) < 1 {
|
||||
return shim.Error("Incorrect number of arguments. Expecting 1")
|
||||
}
|
||||
|
||||
queryString := args[0]
|
||||
|
||||
queryResults, err := getQueryResultForQueryString(stub, queryString)
|
||||
if err != nil {
|
||||
return shim.Error(err.Error())
|
||||
}
|
||||
|
||||
return shim.Success(queryResults)
|
||||
}
|
||||
|
||||
|
||||
func (t *SimpleChaincode) getHistoryForWallet(stub shim.ChaincodeStubInterface, args []string) pb.Response {
|
||||
|
||||
if len(args) < 1 {
|
||||
return shim.Error("Incorrect number of arguments. Expecting 1")
|
||||
}
|
||||
|
||||
walletId := args[0]
|
||||
|
||||
fmt.Printf("- start getHistoryForWallet: %s\n", walletId)
|
||||
|
||||
resultsIterator, err := stub.GetHistoryForKey(walletId)
|
||||
if err != nil {
|
||||
return shim.Error(err.Error())
|
||||
}
|
||||
defer resultsIterator.Close()
|
||||
|
||||
if resultsIterator.HasNext() {
|
||||
modification, err := resultsIterator.Next()
|
||||
if err != nil {
|
||||
return shim.Error(err.Error())
|
||||
}
|
||||
fmt.Println("Returning information related to", string(modification.Value))
|
||||
}
|
||||
|
||||
// buffer is a JSON array containing historic values for the marble
|
||||
var buffer bytes.Buffer
|
||||
buffer.WriteString("[")
|
||||
|
||||
bArrayMemberAlreadyWritten := false
|
||||
for resultsIterator.HasNext() {
|
||||
response, err := resultsIterator.Next()
|
||||
if err != nil {
|
||||
return shim.Error(err.Error())
|
||||
}
|
||||
|
||||
// Add a comma before array members, suppress it for the first array member
|
||||
if bArrayMemberAlreadyWritten == true {
|
||||
buffer.WriteString(",")
|
||||
}
|
||||
|
||||
buffer.WriteString("{\"TxId\":")
|
||||
buffer.WriteString("\"")
|
||||
buffer.WriteString(response.TxId)
|
||||
buffer.WriteString("\"")
|
||||
|
||||
buffer.WriteString(", \"Value\":")
|
||||
|
||||
|
||||
// if it was a delete operation on given key, then we need to set the
|
||||
//corresponding value null. Else, we will write the response.Value
|
||||
//as-is (as the Value itself a JSON marble)
|
||||
if response.IsDelete {
|
||||
buffer.WriteString("null")
|
||||
} else {
|
||||
buffer.WriteString(string(response.Value))
|
||||
}
|
||||
|
||||
buffer.WriteString(", \"Timestamp\":")
|
||||
buffer.WriteString("\"")
|
||||
buffer.WriteString(time.Unix(response.Timestamp.Seconds, int64(response.Timestamp.Nanos)).String())
|
||||
buffer.WriteString("\"")
|
||||
|
||||
buffer.WriteString(", \"IsDelete\":")
|
||||
buffer.WriteString("\"")
|
||||
buffer.WriteString(strconv.FormatBool(response.IsDelete))
|
||||
buffer.WriteString("\"")
|
||||
|
||||
buffer.WriteString("}")
|
||||
bArrayMemberAlreadyWritten = true
|
||||
}
|
||||
|
||||
buffer.WriteString("]")
|
||||
|
||||
fmt.Printf("- getHistoryForWallet returning:\n%s\n", buffer.String())
|
||||
return shim.Success(buffer.Bytes())
|
||||
}
|
||||
|
||||
|
||||
func (t *SimpleChaincode) getAllEntities(stub shim.ChaincodeStubInterface, args []string) pb.Response {
|
||||
|
||||
if len(args) < 2 {
|
||||
return shim.Error("Incorrect number of arguments. Expecting 2")
|
||||
}
|
||||
|
||||
startKey := args[0]
|
||||
endKey := args[1]
|
||||
|
||||
resultsIterator, err := stub.GetStateByRange(startKey, endKey)
|
||||
if err != nil {
|
||||
return shim.Error(err.Error())
|
||||
}
|
||||
defer resultsIterator.Close()
|
||||
|
||||
buffer, err := constructQueryResponseFromIterator(resultsIterator)
|
||||
if err != nil {
|
||||
return shim.Error(err.Error())
|
||||
}
|
||||
|
||||
fmt.Printf("- getAllEntities queryResult:\n%s\n", buffer.String())
|
||||
return shim.Success(buffer.Bytes())
|
||||
}
|
|
@ -1,144 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/hyperledger/fabric/core/chaincode/shim"
|
||||
pb "github.com/hyperledger/fabric/protos/peer"
|
||||
)
|
||||
|
||||
|
||||
// Transaction makes payment of X units from A to B func (t *SimpleChaincode)
|
||||
invoke(stub shim.ChaincodeStubInterface, args []string) pb.Response {
|
||||
var A, B string // Entities
|
||||
var Aval, Bval int // Asset holdings
|
||||
var X int // Transaction value
|
||||
var err error
|
||||
|
||||
if len(args) != 3 {
|
||||
return shim.Error("Incorrect number of arguments. Expecting 3")
|
||||
}
|
||||
|
||||
A = args[0]
|
||||
B = args[1]
|
||||
|
||||
// Get the state from the ledger
|
||||
// TODO: will be nice to have a GetAllState call to ledger
|
||||
Avalbytes, err := stub.GetState(A)
|
||||
if err != nil {
|
||||
return shim.Error("Failed to get state")
|
||||
}
|
||||
if Avalbytes == nil {
|
||||
return shim.Error("Entity not found")
|
||||
}
|
||||
Aval, _ = strconv.Atoi(string(Avalbytes))
|
||||
|
||||
Bvalbytes, err := stub.GetState(B)
|
||||
if err != nil {
|
||||
return shim.Error("Failed to get state")
|
||||
}
|
||||
if Bvalbytes == nil {
|
||||
return shim.Error("Entity not found")
|
||||
}
|
||||
Bval, _ = strconv.Atoi(string(Bvalbytes))
|
||||
|
||||
// Perform the execution
|
||||
X, err = strconv.Atoi(args[2])
|
||||
if err != nil {
|
||||
return shim.Error("Invalid transaction amount, expecting a integer value")
|
||||
}
|
||||
Aval = Aval - X
|
||||
Bval = Bval + X
|
||||
fmt.Printf("Aval = %d, Bval = %d\n", Aval, Bval)
|
||||
|
||||
// Write the state back to the ledger
|
||||
err = stub.PutState(A, []byte(strconv.Itoa(Aval)))
|
||||
if err != nil {
|
||||
return shim.Error(err.Error())
|
||||
}
|
||||
|
||||
err = stub.PutState(B, []byte(strconv.Itoa(Bval)))
|
||||
if err != nil {
|
||||
return shim.Error(err.Error())
|
||||
}
|
||||
|
||||
return shim.Success(nil)
|
||||
}
|
||||
|
||||
|
||||
// Deletes an entity from state
|
||||
func (t *SimpleChaincode) delete(stub shim.ChaincodeStubInterface, args []string) pb.Response {
|
||||
if len(args) != 1 {
|
||||
return shim.Error("Incorrect number of arguments. Expecting 1")
|
||||
}
|
||||
|
||||
A := args[0]
|
||||
|
||||
// Delete the key from the state in ledger
|
||||
err := stub.DelState(A)
|
||||
if err != nil {
|
||||
return shim.Error("Failed to delete state")
|
||||
}
|
||||
|
||||
return shim.Success(nil)
|
||||
}
|
||||
|
||||
|
||||
// query callback representing the query of a chaincode
|
||||
func (t *SimpleChaincode) query(stub shim.ChaincodeStubInterface, args []string) pb.Response {
|
||||
var A string // Entities
|
||||
var err error
|
||||
|
||||
if len(args) != 1 {
|
||||
return shim.Error("Incorrect number of arguments. Expecting name of the person to query")
|
||||
}
|
||||
|
||||
A = args[0]
|
||||
|
||||
// Get the state from the ledger
|
||||
Avalbytes, err := stub.GetState(A)
|
||||
if err != nil {
|
||||
jsonResp := "{\"Error\":\"Failed to get state for " + A + "\"}"
|
||||
return shim.Error(jsonResp)
|
||||
}
|
||||
|
||||
if Avalbytes == nil {
|
||||
jsonResp := "{\"Error\":\"Nil amount for " + A + "\"}"
|
||||
return shim.Error(jsonResp)
|
||||
}
|
||||
|
||||
jsonResp := "{\"Name\":\"" + A + "\",\"Amount\":\"" + string(Avalbytes) + "\"}"
|
||||
fmt.Printf("Query Response:%s\n", jsonResp)
|
||||
return shim.Success(Avalbytes)
|
||||
}
|
||||
|
||||
|
||||
func (t *SimpleChaincode) register(stub shim.ChaincodeStubInterface, args []string) pb.Response {
|
||||
var A string // Entities
|
||||
var Aval int // Asset holdings
|
||||
var err error
|
||||
|
||||
if len(args) != 2 {
|
||||
return shim.Error("Incorrect number of arguments. Expecting 2")
|
||||
}
|
||||
|
||||
// Initialize the chaincode
|
||||
A = args[0]
|
||||
Aval, err = strconv.Atoi(args[1])
|
||||
if err != nil {
|
||||
return shim.Error("Expecting integer value for asset holding")
|
||||
}
|
||||
fmt.Printf("Aval = %d\n", Aval)
|
||||
|
||||
// Write the state to the ledger
|
||||
err = stub.PutState(A, []byte(strconv.Itoa(Aval)))
|
||||
if err != nil {
|
||||
return shim.Error(err.Error())
|
||||
}
|
||||
return shim.Success(nil)
|
||||
}
|
Loading…
Reference in a new issue