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

ingest: Adds basic event parsing for standard Stellar Asset Contract events #4798

Merged
merged 7 commits into from
Mar 9, 2023

Conversation

Shaptic
Copy link
Contributor

@Shaptic Shaptic commented Mar 8, 2023

What

Adds an abstraction layer for standardized contract events that come from the Stellar Asset Contract.

Why

Event parsing is necessary to generate effects and record payments as part of #4722 (and #4725).

Known limitations

This only covers the transfer events generated by calling xfer and xfer_from. It could also use more test cases.

Ideally, @sreuland and I would build the parsing/testing on top of this PR for the events we need as they pertain to our issues.

@Shaptic Shaptic requested review from tamirms, sreuland and a team March 8, 2023 22:01
ingest/event.go Outdated
}

assetBytes, ok := assetContainer.GetBin()
fmt.Println("here", len(assetBytes), assetBytes)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good debug logging, just a little more descriptive, fmt.Printf('SAC asset event received for %v', string(assetBytes)) ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lol I left this in while I was debugging tests 🤦 maybe we shouldn't print stuff in this package? Horizon itself should probably do that, though

@Shaptic Shaptic force-pushed the sac-event-parsing branch from 5b99544 to b76d202 Compare March 8, 2023 23:20
@Shaptic Shaptic requested a review from sreuland March 8, 2023 23:33
@Shaptic Shaptic force-pushed the sac-event-parsing branch from adb9970 to 7cb137c Compare March 8, 2023 23:35
ingest/event.go Outdated
ErrNotTransferEvent = errors.New("event is an invalid 'transfer' event")
)

type StellarAssetContractEvent struct {
Copy link
Contributor

@sreuland sreuland Mar 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This event is meant to model a sub-group of similar functional events from SAC related to balance changes mostly correct? Maybe can indicate that with name like StellarAssetContractBalanceChangedEvent to infer that meaning a bit more?

[edit, not suggesting change now, just for consideration]
Do you think this eventually scales to point of being 1-1, a separate event struct specific to each SAC method, i.e. StellarAssetContract<sac_method>Event, each supporting common interface:

type StellarAssetContractEvent interface {
getType() int
}

NewStellarAssetContractEvent() becomes more polymorphic, returning instance of event specific struct that matched contract event, caller uses getType() to cast to real struct type.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This event is meant to model a sub-group of similar functional events from SAC related to balance changes mostly correct?

I thought, rather, that this would be done for all SAC events, but we'd start with balance-related ones since those have the immediate need. I do like the idea of making it polymorphic (kinda like txnbuild.Operation is, see here), but maybe it's too soon? For now, it's easier to use the struct and just know which fields are set for which types.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep, we don't want to make it too fancy yet, as it may change, but thinking of how callers will use the event struct, they're gonna end up hardcoding what fields in the uber-struct(StellarAssetContractEvent ) are valid for each type of event(xfer, mint, clawback, etc), whereas if we bite the bullet now and capture the fields-per-contract-event in separate structs, then callers can handle different events in more deterministic type-safe way

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah I 100% agree, was just being lazy tbh - added in latest push (a7ebfd6)! is that what you had in mind?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Shaptic , nice, I see you put up #4802 which captures the different event models succinctly, thanks!

switch evt.Type {
case EventTypeTransfer:
return evt, evt.parseTransferEvent(topics, value)
case EventTypeMint:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these seem to return an un-usable event, as only Type has been populated, maybe just throw unsupported also to avoid callers trying to do something, or do you think we can squeeze mint/clawback into the current StellarAssetContractEvent?

I was wondering if mint is qualified for including in payments, I see payments includes CreateAccount operation, which is somewhat similar to mint?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah you're right - this is captured in the docstring: It will return a best-effort parsing even in error cases.. I could see callers actually finding this desirable: it helps debugging where parsing failed (i.e. you can see which fields got parsed correctly and which didn't), and it can also make this a useful parsing mechanism even for custom events. For example, if I have a "SAC-like" event in the form transfer/blah/blah/<asset>, then I can use this helper to extract <asset> without actually conforming as a proper SAC event.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As for payments, I think it should count, because in the Classic world, a "mint" of your custom asset only really happens after you make a PaymentOp to someone. Same thing with burns.

Copy link
Contributor

@sreuland sreuland left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

great work to capture contract events in a re-usable format, I'm sure will iterate more on it, but it provides insight on event model and will be re-used!

@Shaptic Shaptic merged commit 0c5115c into stellar:soroban-xdr-next Mar 9, 2023
@Shaptic Shaptic deleted the sac-event-parsing branch March 9, 2023 01:00
switch address.Type {
case xdr.ScAddressTypeScAddressTypeAccount:
pubkey := address.MustAccountId().Ed25519
fmt.Println("pubkey:", address.MustAccountId())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

another print statement we should remove

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good catches, thanks! should be gone in the other PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants