Skip to content

Commit

Permalink
Merge pull request #10 from patractlabs/features/examples
Browse files Browse the repository at this point in the history
Add examples for rest and observer
  • Loading branch information
polkadev authored Dec 22, 2020
2 parents 7042876 + 9566a93 commit fb6be58
Show file tree
Hide file tree
Showing 10 changed files with 169 additions and 12 deletions.
42 changes: 42 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,48 @@ Call Transfer:
)
```

### Rest

We can use rest to get unsigned raw byte datas for constract call, it can help to build a offline signaturer for contract.

can use this for example: [rest](https://github.com/patractlabs/go-patract/blob/master/examples/rest/main.go)

start the rest server:

```bash
go run ./examples/rest
```

to get data:

```bash
curl -X POST \
'http://localhost:8899/erc20/exec/transfer?isOffline=true&contract=5HKinTRKW9THEJxbQb22Nfyq9FPWNVZ9DQ2GEQ4Vg1LqTPuk' \
-H 'content-type: application/json' \
-d '{
"nonce":1,
"chain_status":{
"spec_version":1,
"tx_version":1,
"block_hash":"0xc20f241b61039e5685d118c7fbc8b27210153c21eee7686a9466f22e01281114",
"genesis_hash":"0xc20f241b61039e5685d118c7fbc8b27210153c21eee7686a9466f22e01281114"
},
"contract":"5HKinTRKW9THEJxbQb22Nfyq9FPWNVZ9DQ2GEQ4Vg1LqTPuk",
"origin":"5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY",
"gas_limit":"500000000000",
"args":{
"to":"5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty",
"value":"100000000"
}
}'
```

### observer

For a contract, we need observer events for the contract, can use `observer` to build a contract events observer service:

example: [observer](https://github.com/patractlabs/go-patract/blob/master/examples/observer/main.go)

## Thanks

- [Centrifuge's GSRPC](https://github.com/centrifuge/go-substrate-rpc-client)
18 changes: 9 additions & 9 deletions api/watch.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"github.com/patractlabs/go-patract/utils/log"
)

type watcher struct {
type Watcher struct {
wg sync.WaitGroup
eventChann chan evtMsgInChann
stat int
Expand All @@ -18,44 +18,44 @@ type watcher struct {
logger log.Logger
}

func NewWatcher(logger log.Logger, url string) *watcher {
func NewWatcher(logger log.Logger, url string) *Watcher {
scanner := NewScanner(logger, url)

return &watcher{
return &Watcher{
scanner: scanner,
cli: scanner.Cli(),
logger: logger,
eventChann: make(chan evtMsgInChann, 4096),
}
}

func (s *watcher) Cli() *Client {
func (s *Watcher) Cli() *Client {
return s.cli
}

func (w *watcher) nextStatStep() {
func (w *Watcher) nextStatStep() {
w.mutex.Lock()
defer w.mutex.Unlock()

w.stat++
}

func (w *watcher) Status() int {
func (w *Watcher) Status() int {
w.mutex.RLock()
defer w.mutex.RUnlock()

return w.stat
}

func (w *watcher) Wait() {
func (w *Watcher) Wait() {
w.logger.Debug("watcher start wait stopped")

w.wg.Wait()

w.logger.Debug("watcher stopped")
}

func (w *watcher) Watch(ctx context.Context, fromHeight uint64, h EventHandler) error {
func (w *Watcher) Watch(ctx context.Context, fromHeight uint64, h EventHandler) error {
w.logger.Debug("start scanner first", "from", fromHeight)

// init the client
Expand Down Expand Up @@ -131,7 +131,7 @@ func (w *watcher) Watch(ctx context.Context, fromHeight uint64, h EventHandler)
return nil
}

func (w *watcher) stop() {
func (w *Watcher) stop() {
w.logger.Debug("watcher start stop")
close(w.eventChann)
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
88 changes: 88 additions & 0 deletions examples/observer/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package main

import (
"context"
"flag"
"io/ioutil"

"github.com/centrifuge/go-substrate-rpc-client/types"
"github.com/patractlabs/go-patract/contracts/erc20"
"github.com/patractlabs/go-patract/metadata"
"github.com/patractlabs/go-patract/observer"
"github.com/patractlabs/go-patract/utils"
"github.com/patractlabs/go-patract/utils/log"
)

var (
flagURL = flag.String("url", "ws://localhost:9944", "url to chain node")
flagContractMetadata = flag.String("metadata", "", "metadata for contract")
flagCodeHash = flag.String("hash", "", "codeHash for contract")
)

func main() {
if !flag.Parsed() {
flag.Parse()
}

logger := log.NewLogger()
defer func() {
logger.Flush()
}()

o := observer.New(logger, *flagURL)
ctx, cancelFunc := context.WithCancel(context.Background())

metaBz, err := ioutil.ReadFile(*flagContractMetadata)
if err != nil {
logger.Error("read metadata err", "err", err, "path", *flagContractMetadata)
return
}

hash, err := types.HexDecodeString(*flagCodeHash)
if err != nil {
logger.Error("hex decode code hash err", "err", err, "path", *flagCodeHash)
return
}

o = o.WithFromHeight(0).WithMetaDataBytes(types.NewHash(hash), metaBz)

metaData := o.MetaData(types.NewHash(hash))

h := observer.NewEvtHandler()
h = h.WithContractExecution(func(l log.Logger, height uint64, evt types.EventContractsContractExecution) {
data := evt.Data

l.Debug("handler contract execution", "height", height)

typ := metadata.GetEvtTypeIdx(data)
switch typ {
case 0:
var transfer erc20.EventTransfer
err := metaData.Spec.Events.DecodeEvt(metaData.NewCtxForDecode(data).WithLogger(l), &transfer)
if err != nil {
logger.Error("evt decode transfer error", "err", err, "height", height)
}
logger.Info("transfer event", "evt", transfer)
case 1:
var approve erc20.EventApproval
err := metaData.Spec.Events.DecodeEvt(metaData.NewCtxForDecode(data).WithLogger(l), &approve)
if err != nil {
logger.Error("evt decode approve error", "err", err, "height", height)
}
logger.Info("approve event", "evt", approve)
}
})

if err := o.WatchEvent(ctx, h); err != nil {
logger.Error("watch event error", "err", err)
return
}

utils.HoldToClose(func() {
cancelFunc()
o.Wait()

logger.Info("observer stop")
logger.Flush()
})
}
10 changes: 7 additions & 3 deletions observer/observer.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ type ContractObserver struct {
fromHeight uint64
contractIDs map[types.AccountID]bool
metaDatas map[types.Hash]*metadata.Data
watcher *api.Watcher
}

func New(logger log.Logger, url string) *ContractObserver {
Expand Down Expand Up @@ -58,9 +59,9 @@ func (w *ContractObserver) MetaData(codeHash types.Hash) *metadata.Data {
}

func (w *ContractObserver) WatchEvent(ctx context.Context, handler *EvtHandler) error {
watcher := api.NewWatcher(w.logger, w.url)
w.watcher = api.NewWatcher(w.logger, w.url)

return watcher.Watch(ctx, w.fromHeight,
return w.watcher.Watch(ctx, w.fromHeight,
func(l log.Logger, height uint64, evt *types.EventRecords) error {

if len(evt.Contracts_Instantiated)+
Expand All @@ -79,8 +80,11 @@ func (w *ContractObserver) WatchEvent(ctx context.Context, handler *EvtHandler)
})
}

func (w *ContractObserver) logContractEvts(height uint64, evt *types.EventRecords) {
func (w *ContractObserver) Wait() {
w.watcher.Wait()
}

func (w *ContractObserver) logContractEvts(height uint64, evt *types.EventRecords) {
w.logger.Debug("block event", "height", height)

for _, e := range evt.Contracts_Instantiated {
Expand Down
9 changes: 9 additions & 0 deletions utils/log/log.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ const (

// Logger a logger interface
type Logger interface {
Flush()

Debug(msg string, args ...interface{})
Info(msg string, args ...interface{})
Warn(msg string, args ...interface{})
Expand Down Expand Up @@ -68,6 +70,13 @@ func tryProcessTypes(arg interface{}) (string, bool) {
return "", false
}

func (l *loggerByZap) Flush() {
err := l.l.Sync()
if err != nil {
fmt.Printf("logger flush error %s", err.Error())
}
}

// Debug imp debug log
func (l *loggerByZap) Debug(msg string, args ...interface{}) {
if len(args) == 0 {
Expand Down
14 changes: 14 additions & 0 deletions utils/os.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package utils

import (
"os"
"os/signal"
"syscall"
)

func HoldToClose(waitFunc func()) {
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
<-c
waitFunc()
}

0 comments on commit fb6be58

Please sign in to comment.