diff --git a/pastel/cascade_multi_volume.go b/pastel/cascade_multi_volume.go deleted file mode 100644 index 1611f1e54..000000000 --- a/pastel/cascade_multi_volume.go +++ /dev/null @@ -1,8 +0,0 @@ -package pastel - -type CascadeMultiVolumeTicket struct { - ID string `json:"id"` - HumanReadableIdentifier string `json:"human_readable_identifier"` - SHA3256HashOfOriginalFile string `json:"sha3_256_hash_of_original_file"` - Volumes map[string]string `json:"volumes"` -} \ No newline at end of file diff --git a/pastel/client.go b/pastel/client.go index 6e5ec8063..2ac3f66ea 100644 --- a/pastel/client.go +++ b/pastel/client.go @@ -12,8 +12,8 @@ import ( "github.com/pastelnetwork/gonode/common/errors" "github.com/pastelnetwork/gonode/common/log" - "github.com/pastelnetwork/gonode/pastel/jsonrpc" "github.com/pastelnetwork/gonode/common/utils" + "github.com/pastelnetwork/gonode/pastel/jsonrpc" ) const ( @@ -25,8 +25,13 @@ const ( TicketTypeInactive RegTicketsFilter = "inactive" // TicketTypeAll is all filter for tickets TicketTypeAll RegTicketsFilter = "all" + + // CascadeMultiVolumeMetadata is the only contract type currently available + CascadeMultiVolumeMetadata ContractType = "cascade_multi_volume_metadata" ) +type ContractType string + // RegTicketsFilter is filter for retrieving action & nft registration tickets type RegTicketsFilter string @@ -290,6 +295,16 @@ func (client *client) RegTicket(ctx context.Context, regTxid string) (RegTicket, return ticket, nil } +func (client *client) GetContractTicket(ctx context.Context, txid string) (Contract, error) { + ticket := Contract{} + + if err := client.callFor(ctx, &ticket, "tickets", "get", txid); err != nil { + return ticket, errors.Errorf("failed to get contract ticket %s: %w", txid, err) + } + + return ticket, nil +} + // ActionRegTicket implements pastel.Client.RegTicket func (client *client) ActionRegTicket(ctx context.Context, regTxid string) (ActionRegTicket, error) { ticket := ActionRegTicket{} @@ -533,30 +548,41 @@ func (client *client) RegisterActionTicket(ctx context.Context, request Register return txID.TxID, nil } -func (client *client) RegisterCascadeMultiVolumeTicket(ctx context.Context, ticket CascadeMultiVolumeTicket) (string, error){ - ticketJSON, err := json.Marshal(ticket) - if err != nil { - return "", errors.Errorf("failed to call register action ticket: %w", err) - } - ticketBlob := base64.StdEncoding.EncodeToString(ticketJSON) +func (client *client) RegisterCascadeMultiVolumeTicket(ctx context.Context, ticket CascadeMultiVolumeTicket) (string, error) { + return client.registerContract(ctx, ticket, CascadeMultiVolumeMetadata) +} + +func (client *client) registerContract(ctx context.Context, data interface{}, contractType ContractType) (string, error) { + ticketJSON, err := json.Marshal(data) + if err != nil { + return "", errors.Errorf("failed to call register action ticket: %w", err) + } + ticketBlob := base64.StdEncoding.EncodeToString(ticketJSON) hash, _ := utils.Sha3256hash(ticketJSON) - // Assuming some additional data or parameters are needed, similar to the RegisterNFTRequest example - params := []interface{}{ - "register", - "contract", - ticketBlob, - ticket.ID, - hash, - } - - resp := make(map[string]interface{}) - if err := client.callFor(ctx, &resp, "tickets", params...); err != nil { - return "", errors.Errorf("failed to call register contract: %w", err) - } - log.WithContext(ctx).WithField("resp", resp).WithField("txid", ticket.ID).Info("RegisterCascadeMultiVolumeTicket Response") - - return ticket.ID, nil + // Assuming some additional data or parameters are needed, similar to the RegisterNFTRequest example + params := []interface{}{ + "register", + "contract", + ticketBlob, + contractType, + hash, + } + + type ContractResponse struct { + TxID string `json:"txid"` + Key string `json:"key"` + } + resp := ContractResponse{} + + if err := client.callFor(ctx, &resp, "tickets", params...); err != nil { + return "", errors.Errorf("failed to call register contract: %w", err) + } + if resp.TxID == "" { + return "", errors.Errorf("failed to call register contract (no txid rcvd.): %w", err) + } + + return resp.TxID, nil } func (client *client) ActivateActionTicket(ctx context.Context, request ActivateActionRequest) (string, error) { diff --git a/pastel/contract.go b/pastel/contract.go new file mode 100644 index 000000000..526b7d618 --- /dev/null +++ b/pastel/contract.go @@ -0,0 +1,65 @@ +package pastel + +import ( + "encoding/base64" + "encoding/json" + "fmt" + + "github.com/pastelnetwork/gonode/common/errors" +) + +// ContractTicket defines the contract ticket +type ContractTicket struct { + ContractTicketData string `json:"contract_ticket"` + Key string `json:"key"` + SecondaryKey string `json:"secondary_key"` + SubType string `json:"sub_type"` + Timestamp int64 `json:"timestamp"` + Type string `json:"type"` + Version int `json:"version"` +} + +// TxInfo defines the transaction information +type TxInfo struct { + CompressedSize int `json:"compressed_size"` + CompressionRatio string `json:"compression_ratio"` + IsCompressed bool `json:"is_compressed"` + MultisigOutputsCount int `json:"multisig_outputs_count"` + MultisigTxTotalFee int `json:"multisig_tx_total_fee"` + UncompressedSize int `json:"uncompressed_size"` +} + +// Contract defines the contract +type Contract struct { + Height int `json:"height"` + Ticket ContractTicket `json:"ticket"` + TxInfo TxInfo `json:"tx_info"` + TxID string `json:"txid"` +} + +// -------------------------------------- Contract Types -------------------------------------------// + +// CascadeMultiVolumeTicket defines the cascade multi volume ticket contract type +type CascadeMultiVolumeTicket struct { + NameOfOriginalFile string `json:"name_of_original_file"` + SizeOfOriginalFileMB int `json:"size_of_original_file_mb"` + SHA3256HashOfOriginalFile string `json:"sha3_256_hash_of_original_file"` + Volumes map[int]string `json:"volumes"` // key (int): index of the volume, value (string): txid of the volume +} + +func (c *Contract) GetCascadeMultiVolumeMetadataTicket() (t CascadeMultiVolumeTicket, err error) { + if c.Ticket.SubType != string(CascadeMultiVolumeMetadata) { + return t, errors.New("contract is not of type cascade_multi_volume_metadata") + } + + data, err := base64.StdEncoding.DecodeString(c.Ticket.ContractTicketData) + if err != nil { + return t, fmt.Errorf("unable to b64 decode contract: %w", err) + } + + if err := json.Unmarshal(data, &t); err != nil { + return t, fmt.Errorf("unable to decode contract: %w", err) + } + + return t, nil +} diff --git a/pastel/pastel.go b/pastel/pastel.go index 4f187e0b0..9db6a7de8 100644 --- a/pastel/pastel.go +++ b/pastel/pastel.go @@ -241,5 +241,10 @@ type Client interface { NFTStorageFee(ctx context.Context, sizeInMB int) (*NFTStorageFeeEstimate, error) // RegisterCascadeMultiVolumeTicket registers a cascade multi-volume ticket + // Command `tickets register contract <>, <>, <>` RegisterCascadeMultiVolumeTicket(ctx context.Context, ticket CascadeMultiVolumeTicket) (string, error) + + // GetContractTicket returns contract ticket. + // Command `tickets get `. + GetContractTicket(ctx context.Context, txid string) (Contract, error) }