fabric-samples/off_chain_data/application-go/transact.go
Stanislav Jakuschevskij 6a5e5ddc12
Add off-chain-data go client application (#1269)
Signed-off-by: Stanislav Jakuschevskij <stas@two-giants.com>
2025-03-05 17:26:33 +00:00

133 lines
2.8 KiB
Go

package main
import (
"context"
"fmt"
"math/rand/v2"
"sync"
atb "offchaindata/contract"
"github.com/google/uuid"
"github.com/hyperledger/fabric-gateway/pkg/client"
"google.golang.org/grpc"
)
var owners = []string{"alice", "bob", "charlie"}
func transact(clientConnection grpc.ClientConnInterface) error {
id, options := newConnectOptions(clientConnection)
gateway, err := client.Connect(id, options...)
if err != nil {
return err
}
defer func() {
gateway.Close()
fmt.Println("Gateway closed.")
}()
contract := gateway.GetNetwork(channelName).GetContract(chaincodeName)
smartContract := atb.NewAssetTransferBasic(contract)
app := newTransactApp(smartContract)
return app.run()
}
type transactApp struct {
smartContract *atb.AssetTransferBasic
batchSize int
}
func newTransactApp(smartContract *atb.AssetTransferBasic) *transactApp {
return &transactApp{smartContract, 10}
}
func (t *transactApp) run() error {
ctx, cancel := context.WithCancelCause(context.Background())
defer cancel(nil)
var wg sync.WaitGroup
for range t.batchSize {
wg.Add(1)
go func() {
defer wg.Done()
select {
case <-ctx.Done():
return
default:
if err := t.transact(); err != nil {
cancel(err)
return
}
}
}()
}
wg.Wait()
return context.Cause(ctx)
}
func (t *transactApp) transact() error {
anAsset, err := newAsset()
if err != nil {
return err
}
if err := t.smartContract.CreateAsset(anAsset); err != nil {
return err
}
fmt.Println("Created asset", anAsset.ID)
// Transfer randomly 1 in 2 assets to a new owner.
if rand.N(2) == 0 {
newOwner := differentElement(owners, anAsset.Owner)
oldOwner, err := t.smartContract.TransferAsset(anAsset.ID, newOwner)
if err != nil {
return err
}
fmt.Printf("Transferred asset %s from %s to %s\n", anAsset.ID, oldOwner, newOwner)
}
// Delete randomly 1 in 4 created assets.
if rand.N(4) == 0 {
if err := t.smartContract.DeleteAsset(anAsset.ID); err != nil {
return err
}
fmt.Println("Deleted asset", anAsset.ID)
}
return nil
}
func newAsset() (atb.Asset, error) {
id, err := uuid.NewRandom()
if err != nil {
return atb.Asset{}, err
}
return atb.Asset{
ID: id.String(),
Color: randomElement([]string{"red", "green", "blue"}),
Size: uint64(rand.N(10) + 1),
Owner: randomElement(owners),
AppraisedValue: uint64(rand.N(1000) + 1),
}, nil
}
// Pick a random element from an array.
func randomElement(values []string) string {
return values[rand.N(len(values))]
}
// Pick a random element from an array, excluding the current value.
func differentElement(values []string, currentValue string) string {
candidateValues := []string{}
for _, v := range values {
if v != currentValue {
candidateValues = append(candidateValues, v)
}
}
return randomElement(candidateValues)
}