Skip to content

Commit

Permalink
[ioctl][ws][#5] project device sub commands to support interaction wi…
Browse files Browse the repository at this point in the history
…th ws contracts (#4283)


* feat(ioctl/ws): ioctl support ws project device contract interactions

---------

Co-authored-by: CoderZhi <thecoderzhi@gmail.com>
  • Loading branch information
saitofun and CoderZhi committed May 30, 2024
1 parent 3ebc017 commit b1e286c
Show file tree
Hide file tree
Showing 4 changed files with 330 additions and 0 deletions.
55 changes: 55 additions & 0 deletions ioctl/cmd/ws/wsdevice.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package ws

import (
"bytes"
_ "embed" // used to embed contract abi

"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/spf13/cobra"

"github.com/iotexproject/iotex-core/ioctl/config"
)

var (
_flagDevicesUsages = map[config.Language]string{
config.English: "device address for the project, separate multiple addresses with commas",
config.Chinese: "该project的设备地址,多个地址用逗号分割",
}
)

var wsProjectDeviceCmd = &cobra.Command{
Use: "device",
Short: config.TranslateInLang(map[config.Language]string{
config.English: "w3bstream device management",
config.Chinese: "w3bstream device 节点管理",
}, config.UILanguage),
}

var (
//go:embed contracts/abis/ProjectDevice.json
projectDeviceJSON []byte
projectDeviceAddress string
projectDeviceABI abi.ABI
)

const (
funcDevicesApprove = "approve"
funcDevicesUnapprove = "unapprove"
funcDevicesApproved = "approved"
)

const (
eventOnApprove = "Approve"
eventOnUnapprove = "Unapprove"
)

func init() {
var err error
projectDeviceABI, err = abi.JSON(bytes.NewReader(projectDeviceJSON))
if err != nil {
panic(err)
}
projectDeviceAddress = config.ReadConfig.WsProjectDevicesContract

WsCmd.AddCommand(wsProjectDeviceCmd)
}
91 changes: 91 additions & 0 deletions ioctl/cmd/ws/wsdeviceapprove.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package ws

import (
"fmt"
"math/big"
"strings"

"github.com/ethereum/go-ethereum/common"
"github.com/pkg/errors"
"github.com/spf13/cobra"

"github.com/iotexproject/iotex-address/address"
"github.com/iotexproject/iotex-core/ioctl/cmd/ws/contracts"
"github.com/iotexproject/iotex-core/ioctl/config"
"github.com/iotexproject/iotex-core/ioctl/output"
)

var (
// wsProjectDeviceApprove represents approve device to send message to w3bstream project command
wsProjectDeviceApprove = &cobra.Command{
Use: "approve",
Short: config.TranslateInLang(wsProjectDeviceApproveShorts, config.UILanguage),
RunE: func(cmd *cobra.Command, args []string) error {
projectID, err := cmd.Flags().GetUint64("project-id")
if err != nil {
return errors.Wrap(err, "failed to get flag project-id")
}
devices, err := cmd.Flags().GetString("devices")
if err != nil {
return errors.Wrap(err, "failed to get flag devices")
}

out, err := approveProjectDevice(projectID, devices)
if err != nil {
return output.PrintError(err)
}
output.PrintResult(out)
return nil
},
}

wsProjectDeviceApproveShorts = map[config.Language]string{
config.English: "approve devices for w3bstream project",
config.Chinese: "授权w3bstream项目的设备",
}
)

func init() {
wsProjectDeviceApprove.Flags().Uint64P("project-id", "", 0, config.TranslateInLang(_flagProjectIDUsages, config.UILanguage))
wsProjectDeviceApprove.Flags().StringP("devices", "", "", config.TranslateInLang(_flagDevicesUsages, config.UILanguage))

_ = wsProjectDeviceApprove.MarkFlagRequired("project-id")
_ = wsProjectDeviceApprove.MarkFlagRequired("devices")

wsProjectDeviceCmd.AddCommand(wsProjectDeviceApprove)
}

func approveProjectDevice(projectID uint64, devices string) (string, error) {
deviceArr := []string{devices}
if strings.Contains(devices, ",") {
deviceArr = strings.Split(devices, ",")
}

deviceAddress := make([]common.Address, len(deviceArr))
for _, device := range deviceArr {
addr, err := address.FromString(device)
if err != nil {
return "", errors.Wrapf(err, "invalid device address: %s", device)
}
deviceAddress = append(deviceAddress, common.BytesToAddress(addr.Bytes()))
}

caller, err := NewContractCaller(projectDeviceABI, projectDeviceAddress)
if err != nil {
return "", errors.Wrap(err, "failed to create contract caller")
}

value := new(contracts.ProjectDeviceApprove)
result := NewContractResult(&projectDeviceABI, eventOnApprove, value)
if _, err = caller.CallAndRetrieveResult(funcDevicesApprove, []any{
big.NewInt(int64(projectID)),
deviceAddress,
}, result); err != nil {
return "", errors.Wrap(err, "failed to read contract")
}
if _, err = result.Result(); err != nil {
return "", err
}

return fmt.Sprintf("approve %d device", len(deviceAddress)), nil
}
93 changes: 93 additions & 0 deletions ioctl/cmd/ws/wsdeviceapproved.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package ws

import (
"math/big"

"github.com/ethereum/go-ethereum/common"
"github.com/pkg/errors"
"github.com/spf13/cobra"

"github.com/iotexproject/iotex-address/address"
"github.com/iotexproject/iotex-core/ioctl/config"
"github.com/iotexproject/iotex-core/ioctl/output"
)

var (
// wsProjectDeviceApproved represents unapprove device to send message to w3bstream project command
wsProjectDeviceApproved = &cobra.Command{
Use: "approved",
Short: config.TranslateInLang(wsProjectDeviceApprovedShorts, config.UILanguage),
RunE: func(cmd *cobra.Command, args []string) error {
projectID, err := cmd.Flags().GetUint64("project-id")
if err != nil {
return errors.Wrap(err, "failed to get flag project-id")
}
device, err := cmd.Flags().GetString("device")
if err != nil {
return errors.Wrap(err, "failed to get flag devices")
}

out, err := approvedProjectDevice(projectID, device)
if err != nil {
return output.PrintError(err)
}
output.PrintResult(output.JSONString(out))
return nil
},
}

wsProjectDeviceApprovedShorts = map[config.Language]string{
config.English: "approved devices for w3bstream project",
config.Chinese: "查询是否授权w3bstream项目的设备",
}

_flagDeviceUsages = map[config.Language]string{
config.English: "device address for the project",
config.Chinese: "该project的设备地址",
}
)

func init() {
wsProjectDeviceApproved.Flags().Uint64P("project-id", "", 0, config.TranslateInLang(_flagProjectIDUsages, config.UILanguage))
wsProjectDeviceApproved.Flags().StringP("device", "", "", config.TranslateInLang(_flagDeviceUsages, config.UILanguage))

_ = wsProjectDeviceApproved.MarkFlagRequired("project-id")
_ = wsProjectDeviceApproved.MarkFlagRequired("device")

wsProjectDeviceCmd.AddCommand(wsProjectDeviceApproved)
}

func approvedProjectDevice(projectID uint64, device string) (any, error) {
addr, err := address.FromString(device)
if err != nil {
return nil, errors.Wrapf(err, "invalid device address: %s", device)
}
deviceAddress := common.BytesToAddress(addr.Bytes())

caller, err := NewContractCaller(projectDeviceABI, projectDeviceAddress)
if err != nil {
return nil, errors.Wrap(err, "failed to create contract caller")
}

result := NewContractResult(&projectDeviceABI, funcDevicesApproved, new(bool))
if err = caller.Read(funcDevicesApproved, []any{
big.NewInt(int64(projectID)),
deviceAddress,
}, result); err != nil {
return nil, errors.Wrap(err, "failed to read contract")
}
approved, err := result.Result()
if err != nil {
return nil, err
}

return &struct {
ProjectID uint64 `json:"projectID"`
Device string `json:"device"`
Approved bool `json:"approved"`
}{
ProjectID: projectID,
Device: device,
Approved: *(approved.(*bool)),
}, nil
}
91 changes: 91 additions & 0 deletions ioctl/cmd/ws/wsdeviceunapprove.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package ws

import (
"fmt"
"math/big"
"strings"

"github.com/ethereum/go-ethereum/common"
"github.com/pkg/errors"
"github.com/spf13/cobra"

"github.com/iotexproject/iotex-address/address"
"github.com/iotexproject/iotex-core/ioctl/cmd/ws/contracts"
"github.com/iotexproject/iotex-core/ioctl/config"
"github.com/iotexproject/iotex-core/ioctl/output"
)

var (
// wsProjectDeviceUnapprove represents unapprove device to send message to w3bstream project command
wsProjectDeviceUnapprove = &cobra.Command{
Use: "unapprove",
Short: config.TranslateInLang(wsProjectDeviceUnapproveShorts, config.UILanguage),
RunE: func(cmd *cobra.Command, args []string) error {
projectID, err := cmd.Flags().GetUint64("project-id")
if err != nil {
return errors.Wrap(err, "failed to get flag project-id")
}
devices, err := cmd.Flags().GetString("devices")
if err != nil {
return errors.Wrap(err, "failed to get flag devices")
}

out, err := unapproveProjectDevice(projectID, devices)
if err != nil {
return output.PrintError(err)
}
output.PrintResult(out)
return nil
},
}

wsProjectDeviceUnapproveShorts = map[config.Language]string{
config.English: "unapprove devices for w3bstream project",
config.Chinese: "取消授权w3bstream项目的设备",
}
)

func init() {
wsProjectDeviceUnapprove.Flags().Uint64P("project-id", "", 0, config.TranslateInLang(_flagProjectIDUsages, config.UILanguage))
wsProjectDeviceUnapprove.Flags().StringP("devices", "", "", config.TranslateInLang(_flagDevicesUsages, config.UILanguage))

_ = wsProjectDeviceUnapprove.MarkFlagRequired("project-id")
_ = wsProjectDeviceUnapprove.MarkFlagRequired("devices")

wsProjectDeviceCmd.AddCommand(wsProjectDeviceUnapprove)
}

func unapproveProjectDevice(projectID uint64, devices string) (string, error) {
deviceArr := []string{devices}
if strings.Contains(devices, ",") {
deviceArr = strings.Split(devices, ",")
}

deviceAddress := make([]common.Address, len(deviceArr))
for _, device := range deviceArr {
addr, err := address.FromString(device)
if err != nil {
return "", errors.Wrapf(err, "invalid device address: %s", device)
}
deviceAddress = append(deviceAddress, common.BytesToAddress(addr.Bytes()))
}

caller, err := NewContractCaller(projectDeviceABI, projectDeviceAddress)
if err != nil {
return "", errors.Wrap(err, "failed to create contract caller")
}

value := new(contracts.ProjectDeviceUnapprove)
result := NewContractResult(&projectDeviceABI, eventOnUnapprove, value)
if _, err = caller.CallAndRetrieveResult(funcDevicesUnapprove, []any{
big.NewInt(int64(projectID)),
deviceAddress,
}, result); err != nil {
return "", errors.Wrap(err, "failed to read contract")
}
if _, err = result.Result(); err != nil {
return "", err
}

return fmt.Sprintf("unapprove %d device", len(deviceAddress)), nil
}

0 comments on commit b1e286c

Please sign in to comment.