Skip to content

Commit e60be69

Browse files
committed
update event structs and add off chain requests with payment request as first example
1 parent 1016f8f commit e60be69

3 files changed

Lines changed: 97 additions & 37 deletions

File tree

currencies.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ var CurrencyCodes = map[uint8]string{
182182
178: "ZWG",
183183
}
184184

185-
func GetCurrencyCode(currencyId uint8) OffChainReferenceData {
185+
func GetCurrencyCodeAsOffChainReferenceData(currencyId uint8) OffChainReferenceData {
186186
result := OffChainReferenceData{
187187
Source: OffChainReferenceDataSource{
188188
Type: "ISO Standard",
@@ -200,3 +200,11 @@ func GetCurrencyCode(currencyId uint8) OffChainReferenceData {
200200
result.Data["currency_code"] = currencyCode
201201
return result
202202
}
203+
204+
func GetCurrencyCode(currencyId uint8) string {
205+
currencyCode, ok := CurrencyCodes[currencyId]
206+
if !ok {
207+
return "Unknown"
208+
}
209+
return currencyCode
210+
}

event_processing.go

Lines changed: 9 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,14 @@ import (
2323
"github.com/smartcontractkit/cre-sdk-go/cre"
2424
)
2525

26-
func BuildVerifiableEvent(workflow Workflow, trigger Trigger, event Event, referenceData ReferenceData) VerifiableEvent {
26+
func BuildAndHashVerifiableEvent(domain string, trigger Trigger, event Event, referenceData ReferenceData) PreConsensusEventResults {
27+
verifiableEvent := BuildVerifiableEvent(domain, trigger, event, referenceData)
28+
return HashVerifiableEvent(verifiableEvent)
29+
}
30+
31+
func BuildVerifiableEvent(domain string, trigger Trigger, event Event, referenceData ReferenceData) VerifiableEvent {
2732
return VerifiableEvent{
28-
CreatedAt: time.Now().UTC(),
29-
Workflow: workflow,
33+
Domain: domain,
3034
Trigger: trigger,
3135
Event: event,
3236
ReferenceData: referenceData,
@@ -36,7 +40,7 @@ func BuildVerifiableEvent(workflow Workflow, trigger Trigger, event Event, refer
3640
func HashVerifiableEvent(verifiableEvent VerifiableEvent) PreConsensusEventResults {
3741
marshalledVerifiableEvent, _ := json.Marshal(verifiableEvent)
3842
base64VerifiableEvent := base64.StdEncoding.EncodeToString(marshalledVerifiableEvent)
39-
typeName := verifiableEvent.Workflow.Domain + "." + verifiableEvent.Event.EventName
43+
typeName := verifiableEvent.Domain + "." + verifiableEvent.Event.EventName
4044
payloadToSign := typeName + "." + base64VerifiableEvent
4145
eventHash := crypto.Keccak256Hash([]byte(payloadToSign))
4246

@@ -60,20 +64,14 @@ func GenerateAndPostReport(cfg *Config, rt cre.Runtime, pre PreConsensusEventRes
6064
}
6165
rpb := report.X_GeneratedCodeOnly_Unwrap()
6266

63-
// Convert ChainSelector to uint64
64-
chainSelector, err := strconv.ParseUint(cfg.ChainSelector, 10, 64)
65-
if err != nil {
66-
return "", fmt.Errorf("invalid chain selector: %w", err)
67-
}
68-
6967
// Compose HTTP body
7068
bodyMap := map[string]any{
7169
"event_id": uuid.New().String(),
7270
"created_at": int64(pre.BlockTimestamp) * 1000, // Convert seconds to milliseconds for server
7371
"watcher_id": cfg.WatcherID,
7472
"domain": cfg.Service,
7573
"name": cfg.DetectEventTriggerConfig.ContractEventName,
76-
"chain_selector": chainSelector,
74+
"chain_selector": cfg.ChainSelector,
7775
"address": cfg.DetectEventTriggerConfig.ContractAddress,
7876
"ocr_report": "0x" + hex.EncodeToString(rpb.RawReport),
7977
"ocr_context": "0x" + hex.EncodeToString(rpb.ReportContext),
@@ -115,15 +113,6 @@ func GenerateAndPostReport(cfg *Config, rt cre.Runtime, pre PreConsensusEventRes
115113
return pre.Base64Event, nil
116114
}
117115

118-
func BuildWorkflow(cfg *Config, donID, domain string) Workflow {
119-
return Workflow{
120-
WorkflowName: cfg.WorkflowName,
121-
WatcherID: cfg.WatcherID,
122-
DonID: donID,
123-
Domain: domain,
124-
}
125-
}
126-
127116
func BuildTrigger(chainID string, payload *evm.Log) Trigger {
128117
return Trigger{
129118
ChainID: chainID,

types.go

Lines changed: 79 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
11
package workflows
22

33
import (
4+
"encoding/json"
5+
"fmt"
6+
"strconv"
47
"time"
58

69
gethCommon "github.com/ethereum/go-ethereum/common"
710
)
811

12+
const (
13+
PaymentRequestType = "payment_request"
14+
)
15+
916
// CursorInfo contains parsed info from a "block-logIndex-txHash" string.
1017
type CursorInfo struct {
1118
BlockNumber uint64
@@ -14,39 +21,32 @@ type CursorInfo struct {
1421
}
1522

1623
type VerifiableEvent struct {
17-
CreatedAt time.Time `json:"created_at"`
18-
Workflow Workflow `json:"workflow"`
19-
Trigger Trigger `json:"trigger"`
24+
Domain string `json:"domain"`
2025
Event Event `json:"event"`
2126
ReferenceData ReferenceData `json:"reference_data"`
22-
}
23-
24-
type Workflow struct {
25-
WorkflowName string `json:"workflow_name"`
26-
WatcherID string `json:"watcher_id"`
27-
DonID string `json:"don_id"`
28-
Domain string `json:"domain"`
27+
Trigger Trigger `json:"trigger"`
2928
}
3029

3130
type Trigger struct {
3231
ChainID string `json:"chain_id"`
33-
TxHash string `json:"tx_hash"`
3432
LogIndex uint64 `json:"log_index"`
33+
TxHash string `json:"tx_hash"`
3534
}
3635

3736
type Event struct {
37+
BlockNumber uint64 `json:"block_number"`
38+
BlockTimestamp time.Time `json:"block_timestamp"`
39+
ContractAddress string `json:"contract_address"`
3840
EventName string `json:"event_name"`
3941
EventSignature string `json:"event_signature"`
40-
ContractAddress string `json:"contract_address"`
4142
TopicHash string `json:"topic_hash"`
42-
BlockNumber uint64 `json:"block_number"`
43-
BlockTimestamp time.Time `json:"block_timestamp"`
4443
Args map[string]any `json:"args"`
4544
}
4645

4746
type ReferenceData struct {
48-
OnChain []OnChainReferenceData `json:"on_chain"`
49-
OffChain []OffChainReferenceData `json:"off_chain"`
47+
OnChain []OnChainReferenceData `json:"on_chain,omitempty"`
48+
OffChain []OffChainReferenceData `json:"off_chain,omitempty"`
49+
Requests []OffChainRequest `json:"requests,omitempty"`
5050
}
5151

5252
type OnChainReferenceData struct {
@@ -71,6 +71,69 @@ type OffChainReferenceDataSource struct {
7171
Identifier string `json:"identifier"`
7272
}
7373

74+
// OffChainRequest represents a request to be forwarded to an off-chain application.
75+
// The Type field determines which request type is contained in the Request field.
76+
// Use json.RawMessage to allow consumers to unmarshal the Request based on Type.
77+
type OffChainRequest struct {
78+
Type string `json:"type" example:"payment"`
79+
Request json.RawMessage `json:"request"`
80+
}
81+
82+
// Fixed2 represents a fixed-point decimal number with 2 decimal places, stored as a string.
83+
// Example: "100.00" represents 100.00
84+
type Fixed2 float64
85+
86+
func (f Fixed2) MarshalJSON() ([]byte, error) {
87+
return fmt.Appendf(nil, "%.2f", f), nil
88+
}
89+
90+
func (f *Fixed2) UnmarshalJSON(data []byte) error {
91+
// Try unmarshaling as a float64
92+
var num float64
93+
err := json.Unmarshal(data, &num)
94+
if err == nil {
95+
*f = Fixed2(num)
96+
return nil
97+
}
98+
99+
// Fallback: try as a quoted string
100+
var s string
101+
if err := json.Unmarshal(data, &s); err != nil {
102+
return fmt.Errorf("Fixed2: invalid JSON input: %w", err)
103+
}
104+
parsed, err := strconv.ParseFloat(s, 64)
105+
if err != nil {
106+
return fmt.Errorf("Fixed2: cannot parse string value: %w", err)
107+
}
108+
*f = Fixed2(parsed)
109+
return nil
110+
}
111+
112+
// PaymentRequest contains the details needed for an off-chain payment request.
113+
type PaymentRequest struct {
114+
ApplicationType string `json:"applicationType" example:"DVP"`
115+
ApplicationAddr string `json:"applicationAddr" example:"0xApplicationAddress"`
116+
E2EID string `json:"e2eId" example:"E2E1234"`
117+
Sender string `json:"sender" example:"0xSenderAddress"`
118+
Receiver string `json:"receiver" example:"0xReceiverAddress"`
119+
Currency string `json:"currency" example:"USD"`
120+
ChainID string `json:"chainId" example:"1337"`
121+
Amount Fixed2 `json:"amount" example:"100.00"`
122+
Expiration *int64 `json:"expiration,omitempty" example:"1257894000"`
123+
// Callback specifies how the off-chain payment handler should call back to the application.
124+
// This can be a function signature (e.g., "fulfillPayment(bytes32,uint256)") or
125+
// a more detailed callback specification.
126+
CustomCallback *PaymentCallback `json:"customCallback,omitempty"`
127+
}
128+
129+
// PaymentCallback specifies how to call back to the application after payment processing.
130+
type PaymentCallback struct {
131+
// FunctionSignature is the ABI function signature to call (e.g., "fulfillPayment(bytes32,uint256)")
132+
FunctionSignature string `json:"functionSignature,omitempty" example:"fulfillPayment(bytes32,uint256)"`
133+
// ContractAddress is the contract address to call. If empty, uses ApplicationAddr from PaymentRequest.
134+
ContractAddress string `json:"contractAddress,omitempty" example:"0xContractAddress"`
135+
}
136+
74137
// PreConsensusEventResults holds the encoded event and hash used for consensus.
75138
type PreConsensusEventResults struct {
76139
Base64Event string

0 commit comments

Comments
 (0)