Compare commits
2 commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
9792677030 | ||
![]() |
933e063af6 |
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
|
Loading…
Reference in a new issue