Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: list groups by ids #191

Merged
merged 2 commits into from
Sep 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 105 additions & 0 deletions client/api_group.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ type Group interface {
// ListGroupsByOwner returns a list of groups owned by the specified user, including those for which the user's expiration time has already elapsed
// By default, the user is the sender. Other users can be set using the option
ListGroupsByOwner(ctx context.Context, opts types.GroupsOwnerPaginationOptions) (*types.GroupsResult, error)
ListGroupsByGroupID(ctx context.Context, groupIDs []uint64, opts types.EndPointOptions) (types.ListGroupsByGroupIDResponse, error)
}

// CreateGroup create a new group on greenfield chain, the group members can be initialized or not
Expand Down Expand Up @@ -568,3 +569,107 @@ func (c *client) ListGroupsByOwner(ctx context.Context, opts types.GroupsOwnerPa

return groups, nil
}

type gfSpListGroupsByGroupIDsResponse map[uint64]*types.GroupMeta

type groupEntry struct {
Id uint64
Value *types.GroupMeta
}

// UnmarshalXML unmarshal gfSpListGroupsByGroupIDsResponse xml response type
func (m *gfSpListGroupsByGroupIDsResponse) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
*m = gfSpListGroupsByGroupIDsResponse{}
for {
var e groupEntry

err := d.Decode(&e)
if err == io.EOF {
break
} else if err != nil {
return err
} else {
(*m)[e.Id] = e.Value
}
}
return nil
}

// ListGroupsByGroupID - List groups by group ids.
//
// By inputting a collection of group IDs, we can retrieve the corresponding object data. If the group is nonexistent or has been deleted, a null value will be returned
//
// - ctx: Context variables for the current API call.
//
// - groupIDs: The list of group ids.
//
// - opts: The options to set the meta to list groups by group id.
//
// - ret1: The result of group info map by given group ids.
//
// - ret2: Return error when the request failed, otherwise return nil.
func (c *client) ListGroupsByGroupID(ctx context.Context, groupIDs []uint64, opts types.EndPointOptions) (types.ListGroupsByGroupIDResponse, error) {
const MaximumListBucketsSize = 1000
if len(groupIDs) == 0 || len(groupIDs) > MaximumListBucketsSize {
return types.ListGroupsByGroupIDResponse{}, nil
}

groupIDMap := make(map[uint64]bool)
for _, id := range groupIDs {
if _, ok := groupIDMap[id]; ok {
// repeat id keys in request
return types.ListGroupsByGroupIDResponse{}, nil
}
groupIDMap[id] = true
}

idStr := make([]string, len(groupIDs))
for i, id := range groupIDs {
idStr[i] = strconv.FormatUint(id, 10)
}
IDs := strings.Join(idStr, ",")

params := url.Values{}
params.Set("groups-query", "")
params.Set("ids", IDs)

reqMeta := requestMeta{
urlValues: params,
contentSHA256: types.EmptyStringSHA256,
}

sendOpt := sendOptions{
method: http.MethodGet,
disableCloseBody: true,
}

endpoint, err := c.getEndpointByOpt(&opts)
if err != nil {
log.Error().Msg(fmt.Sprintf("get endpoint by option failed %s", err.Error()))
return types.ListGroupsByGroupIDResponse{}, err

}

resp, err := c.sendReq(ctx, reqMeta, &sendOpt, endpoint)
if err != nil {
return types.ListGroupsByGroupIDResponse{}, err
}
defer utils.CloseResponse(resp)

buf := new(strings.Builder)
_, err = io.Copy(buf, resp.Body)
if err != nil {
log.Error().Msgf("the list of groups in group ids:%v failed: %s", groupIDs, err.Error())
return types.ListGroupsByGroupIDResponse{}, err
}

groups := types.ListGroupsByGroupIDResponse{}
bufStr := buf.String()
err = xml.Unmarshal([]byte(bufStr), (*gfSpListGroupsByGroupIDsResponse)(&groups.Groups))
if err != nil && groups.Groups == nil {
log.Error().Msgf("the list of groups in group ids:%v failed: %s", groups, err.Error())
return types.ListGroupsByGroupIDResponse{}, err
}

return groups, nil
}
13 changes: 13 additions & 0 deletions examples/group.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,19 @@ func main() {
log.Printf("name: %s, source type: %s\n", group.Group.GroupName, group.Group.SourceType)
}

ids := []uint64{1, 2, 333}
// list groups by group ids
groupList, err := cli.ListGroupsByGroupID(ctx, ids, types.EndPointOptions{
Endpoint: httpsAddr,
SPAddress: "",
})
log.Println("list groups result:")
for _, group := range groupList.Groups {
if group != nil {
log.Printf("name: %s, source type: %s\n", group.Group.GroupName, group.Group.SourceType)
}
}

// delete group
delTx, err := cli.DeleteGroup(ctx, groupName, types.DeleteGroupOption{})
handleErr(err, "DeleteGroup")
Expand Down
6 changes: 3 additions & 3 deletions examples/payment.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,11 @@ func main() {
handleErr(err, "GetStreamRecord")
log.Printf("stream record has balance %s", streamRecordAfterWithdraw.StaticBalance)
streamRecords, err := cli.ListUserPaymentAccounts(ctx, types.ListUserPaymentAccountsOptions{
Account: "0x4FEAA841B3436624C54B652695320830FCB1B309",
Account: "0x6bda8d05a24688f1f2ed05e503d19576aba7da2c",
Endpoint: httpsAddr,
SPAddress: "",
})
for _, record := range streamRecords.StreamRecords {
log.Printf("stream record %s", record.StreamRecord.OutFlowCount)
for _, record := range streamRecords.PaymentAccounts {
log.Printf("payment account %s", record.PaymentAccount.Address)
}
}
30 changes: 25 additions & 5 deletions types/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@ type ListBucketsByPaymentAccountResult struct {
}

type ListUserPaymentAccountsResult struct {
// StreamRecords defines the list of stream records
StreamRecords []*StreamRecordsMeta `xml:"StreamRecords"`
// PaymentAccount defines the list of payment accounts
PaymentAccounts []*PaymentAccounts `xml:"PaymentAccounts"`
}

type ListGroupsResult struct {
Expand Down Expand Up @@ -274,6 +274,12 @@ type ListBucketsByBucketIDResponse struct {
Buckets map[uint64]*BucketMeta `xml:"Buckets"`
}

// ListGroupsByGroupIDResponse is response type for the ListGroupsByGroupID
type ListGroupsByGroupIDResponse struct {
// Groups defines the information of a group map
Groups map[uint64]*GroupMeta `xml:"Groups"`
}

// GroupMeta is the structure for group information
type GroupMeta struct {
// group defines the basic group info
Expand Down Expand Up @@ -308,11 +314,11 @@ type GroupInfo struct {
Extra string `xml:"Extra"`
}

type StreamRecordsMeta struct {
type PaymentAccounts struct {
// refundable defines the payment account is refundable or not
PaymentAccount *PaymentAccount `xml:"PaymentAccount"`
// stream_records defines stream payment records of a stream account
StreamRecord *StreamRecord `xml:"StreamRecord"`
// refundable defines the payment account is refundable or not
Refundable bool `xml:"Refundable"`
}

// StreamRecord defines Record of a stream account
Expand Down Expand Up @@ -341,6 +347,20 @@ type StreamRecord struct {
FrozenNetflowRate int64 `xml:"FrozenNetflowRate"`
}

// PaymentAccount defines payment account info
type PaymentAccount struct {
// Address defines the address of payment account
Address string `xml:"Address"`
// Owner defines the owner of this payment account
Owner string `xml:"Owner"`
// Refundable defines the payment account is refundable or not
Refundable bool `xml:"Refundable"`
// UpdateAt defines the update block height of this payment account
UpdateAt int64 `xml:"UpdateAt"`
// UpdateTime defines the update time of this payment account
UpdateTime int64 `xml:"UpdateTime"`
}

type ListObjectPoliciesResponse struct {
Policies []*PolicyMeta `xml:"Policies"`
}
Expand Down
Loading