near / near-sdk-rs

Rust library for writing NEAR smart contracts
https://near-sdk.io
Apache License 2.0
465 stars 249 forks source link

List of odd APIs #387

Open matklad opened 3 years ago

matklad commented 3 years ago

This issue is for me to brain dump all API papercuts I find, just so that I don't forget about them

4.0 Breaking release:

4.0 Stretch goal:

Future changes:

austinabell commented 3 years ago

The most prevalent one I've been thinking about has been around the collections API, specifically the map types.

It would be ideal if the API matches BTreeMap/HashMap closely. Specifically, the annoying point was for accessor methods, where the functions accepted &K where you really only need any generic type Q (in std for example) where K: Borrow<Q> which might seem like a small difference, but if you have a &str and the key type is String, you need to convert it to a string and take a reference to it, which is unergonomic and less performant. This does open the compiled code size to be larger due to added generics use, but I think it's worth exploring.

I think it would be also awesome if we added the entry API to these types, which would come with some overhead of having to cache all values (which I think is a thing to strive for anyway to avoid redundant storage reads), but it allows for some very clean usage.

If these data structures are modified to cache loaded values from storage, which would take some careful checking of the safety to make sure the API couldn't be misused, we can have APIs for these collections that more closely match std and also potentially save on gas usages from redundant reads.

I'll edit this comment with other ideas to list in the same form as your list, I just needed to add some additional context for this example because it's larger.

matklad commented 3 years ago

Right, there's also a minor point that UnorderedMap is unlikely to be the best name -- it feels like a carry over from C++, where this name was chosen due to backwards compatibility concerns: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1456.html

evgenykuzyakov commented 3 years ago

I'd also recommend replace AccountId from being a String to be struct(pub Vec<u8>), so we don't need to call from_utf8 when not necessary

austinabell commented 3 years ago

I'd also recommend replace AccountId from being a String to be struct(pub Vec<u8>), so we don't need to call from_utf8 when not necessary

Can the AccountId be non-utf8 bytes on-chain? Seems like you're sacrificing developer UX for slightly cleaner code internally? Ideally, we don't expose the internal value to make keeping semver easier.

austinabell commented 3 years ago

Okay, I've updated the original post by changing to checkboxes for completion, linking to PRs, and separating it into potential 4.0 upgrades and future updates.

Feel free for anyone to add anything or change where the items are if you think anything should/shouldn't be included

austinabell commented 3 years ago

Also as a point of discussion, possibly in this release, we can rename some of the VMContext attributes ref https://github.com/near/near-sdk-rs/issues/14. This is currently a breaking change because all fields are publicly exposed (which is a nightmare to maintain), but can be easily phased out depending on if people have started to switch over to VMContextBuilder and don't modify the VMContext directly. Does anyone have thoughts?

Perhaps this can be in a future release, as it would be annoying to migrate for only a cosmetic change

matklad commented 3 years ago

Note that VMContext is a type which comes from nearcore, so we can't just rename the fields. Although it seems it also is amentable to the re-definition trick (together with VMConfig). I would't try to do renames just now: I think we shot for minimally disruptive release, and what just to untie our hands.

So:

austinabell commented 3 years ago

Added switching storage key type to the list of future improvements based on https://github.com/near/near-sdk-rs/pull/402#discussion_r652567138. I've kept in future changes because changing the trait return type can add additional breakages that might be unwanted. Alternatively or before then can just change the types which contain the keys (collections) to Box<[u8]> and just convert it before initializing.

Possibly could be added in the next release though, does anyone have thoughts?

matklad commented 3 years ago

Something which occurred to me yesterday: in env, we have functions like env::current_account_id or env::block_height. Another way to spell this would be making the functions associated methods of the corresponding types: AccountId::current, BlockHeight::current. Not entirely sure which design is better. I think I have a slight preference towards the status quo.