159 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
		
		
			
		
	
	
			159 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
|   | package api | ||
|  | 
 | ||
|  | import ( | ||
|  | 	"encoding/json" | ||
|  | 	"fmt" | ||
|  | 	"math/big" | ||
|  | 
 | ||
|  | 	"github.com/ethereum/go-ethereum/rpc/shared" | ||
|  | ) | ||
|  | 
 | ||
|  | type WhisperMessageArgs struct { | ||
|  | 	Payload  string | ||
|  | 	To       string | ||
|  | 	From     string | ||
|  | 	Topics   []string | ||
|  | 	Priority uint32 | ||
|  | 	Ttl      uint32 | ||
|  | } | ||
|  | 
 | ||
|  | func (args *WhisperMessageArgs) UnmarshalJSON(b []byte) (err error) { | ||
|  | 	var obj []struct { | ||
|  | 		Payload  string | ||
|  | 		To       string | ||
|  | 		From     string | ||
|  | 		Topics   []string | ||
|  | 		Priority interface{} | ||
|  | 		Ttl      interface{} | ||
|  | 	} | ||
|  | 
 | ||
|  | 	if err = json.Unmarshal(b, &obj); err != nil { | ||
|  | 		return shared.NewDecodeParamError(err.Error()) | ||
|  | 	} | ||
|  | 
 | ||
|  | 	if len(obj) < 1 { | ||
|  | 		return shared.NewInsufficientParamsError(len(obj), 1) | ||
|  | 	} | ||
|  | 	args.Payload = obj[0].Payload | ||
|  | 	args.To = obj[0].To | ||
|  | 	args.From = obj[0].From | ||
|  | 	args.Topics = obj[0].Topics | ||
|  | 
 | ||
|  | 	var num *big.Int | ||
|  | 	if num, err = numString(obj[0].Priority); err != nil { | ||
|  | 		return err | ||
|  | 	} | ||
|  | 	args.Priority = uint32(num.Int64()) | ||
|  | 
 | ||
|  | 	if num, err = numString(obj[0].Ttl); err != nil { | ||
|  | 		return err | ||
|  | 	} | ||
|  | 	args.Ttl = uint32(num.Int64()) | ||
|  | 
 | ||
|  | 	return nil | ||
|  | } | ||
|  | 
 | ||
|  | type WhisperIdentityArgs struct { | ||
|  | 	Identity string | ||
|  | } | ||
|  | 
 | ||
|  | func (args *WhisperIdentityArgs) UnmarshalJSON(b []byte) (err error) { | ||
|  | 	var obj []interface{} | ||
|  | 	if err := json.Unmarshal(b, &obj); err != nil { | ||
|  | 		return shared.NewDecodeParamError(err.Error()) | ||
|  | 	} | ||
|  | 
 | ||
|  | 	if len(obj) < 1 { | ||
|  | 		return shared.NewInsufficientParamsError(len(obj), 1) | ||
|  | 	} | ||
|  | 
 | ||
|  | 	argstr, ok := obj[0].(string) | ||
|  | 	if !ok { | ||
|  | 		return shared.NewInvalidTypeError("arg0", "not a string") | ||
|  | 	} | ||
|  | 
 | ||
|  | 	args.Identity = argstr | ||
|  | 
 | ||
|  | 	return nil | ||
|  | } | ||
|  | 
 | ||
|  | type WhisperFilterArgs struct { | ||
|  | 	To     string | ||
|  | 	From   string | ||
|  | 	Topics [][]string | ||
|  | } | ||
|  | 
 | ||
|  | // UnmarshalJSON implements the json.Unmarshaler interface, invoked to convert a | ||
|  | // JSON message blob into a WhisperFilterArgs structure. | ||
|  | func (args *WhisperFilterArgs) UnmarshalJSON(b []byte) (err error) { | ||
|  | 	// Unmarshal the JSON message and sanity check | ||
|  | 	var obj []struct { | ||
|  | 		To     interface{} `json:"to"` | ||
|  | 		From   interface{} `json:"from"` | ||
|  | 		Topics interface{} `json:"topics"` | ||
|  | 	} | ||
|  | 	if err := json.Unmarshal(b, &obj); err != nil { | ||
|  | 		return shared.NewDecodeParamError(err.Error()) | ||
|  | 	} | ||
|  | 	if len(obj) < 1 { | ||
|  | 		return shared.NewInsufficientParamsError(len(obj), 1) | ||
|  | 	} | ||
|  | 	// Retrieve the simple data contents of the filter arguments | ||
|  | 	if obj[0].To == nil { | ||
|  | 		args.To = "" | ||
|  | 	} else { | ||
|  | 		argstr, ok := obj[0].To.(string) | ||
|  | 		if !ok { | ||
|  | 			return shared.NewInvalidTypeError("to", "is not a string") | ||
|  | 		} | ||
|  | 		args.To = argstr | ||
|  | 	} | ||
|  | 	if obj[0].From == nil { | ||
|  | 		args.From = "" | ||
|  | 	} else { | ||
|  | 		argstr, ok := obj[0].From.(string) | ||
|  | 		if !ok { | ||
|  | 			return shared.NewInvalidTypeError("from", "is not a string") | ||
|  | 		} | ||
|  | 		args.From = argstr | ||
|  | 	} | ||
|  | 	// Construct the nested topic array | ||
|  | 	if obj[0].Topics != nil { | ||
|  | 		// Make sure we have an actual topic array | ||
|  | 		list, ok := obj[0].Topics.([]interface{}) | ||
|  | 		if !ok { | ||
|  | 			return shared.NewInvalidTypeError("topics", "is not an array") | ||
|  | 		} | ||
|  | 		// Iterate over each topic and handle nil, string or array | ||
|  | 		topics := make([][]string, len(list)) | ||
|  | 		for idx, field := range list { | ||
|  | 			switch value := field.(type) { | ||
|  | 			case nil: | ||
|  | 				topics[idx] = []string{} | ||
|  | 
 | ||
|  | 			case string: | ||
|  | 				topics[idx] = []string{value} | ||
|  | 
 | ||
|  | 			case []interface{}: | ||
|  | 				topics[idx] = make([]string, len(value)) | ||
|  | 				for i, nested := range value { | ||
|  | 					switch value := nested.(type) { | ||
|  | 					case nil: | ||
|  | 						topics[idx][i] = "" | ||
|  | 
 | ||
|  | 					case string: | ||
|  | 						topics[idx][i] = value | ||
|  | 
 | ||
|  | 					default: | ||
|  | 						return shared.NewInvalidTypeError(fmt.Sprintf("topic[%d][%d]", idx, i), "is not a string") | ||
|  | 					} | ||
|  | 				} | ||
|  | 			default: | ||
|  | 				return shared.NewInvalidTypeError(fmt.Sprintf("topic[%d]", idx), "not a string or array") | ||
|  | 			} | ||
|  | 		} | ||
|  | 		args.Topics = topics | ||
|  | 	} | ||
|  | 	return nil | ||
|  | } |