Rust is increasingly used as a programming language for smart contracts.Whereas the first generation blockchains used specialized VMs,newer blockchains are running general purpose VMs,especially WASM.And of course,Rust is a modern language that runs just about everywhere,and is especially good at targetting WASM.Somewhat serendipitously,this has made Rust one of the best candidate languages for writingsmart contracts on the new generation of blockchains.
Welcome to the Rabid Rabbit Rust Electricity 101: Component Guide series!This series will cover each of the electrical components available in the Rust video.
Lately I’ve been learning more about the smart contract programming landscape,and this post is about my first dive into smart contract programming inRust on the NEAR platform.
NEAR is a sharded, proof-of-stake blockchain that runs WASM.It not only supports smart contracts written in Rust(in addition to AssemblyScript),but is also itself written in Rust.While one the most prominent Rust blockchain projects,it is perhaps not yet widely known in the broader blockchain development community.
Based on my experiences here though,I’m quite enthusiastic about the NEAR developer experience,and I intend to spend more time hacking on NEAR.
These are my first impressions of NEAR,as someone with moderate knowledge of blockchains,but limited previous blockchain programing experience.I have previously written similarly about my first experienceswith other blockchains: Nervos, Ethereum.
The NEAR documentation seems refreshingly thorough,if a bit confusing to navigate.There are different docs to follow depending on your role in the network,whether a validator,smart contract programmer,etc.and I find myself jumping between multiple sections,without quite understanding how the docs are organized overall,perhaps because there isn’t a single table of contents that covers the entire site.
Anyway, after browsing the docs to get a general idea of their organization,I go back to the front page and I click “Basics”.This seems to be leading me down the path of being a smart contract developer,not running my own local node,not building NEAR itself.
For sake of understanding,I generally want to build the entire stack I’m working on,but for now I’m going to follow the docs exactly and see where that gets me,and not build NEAR on my own.
Setting up an account is done through a web interface at:
I create a testnet account,
floopy.testnet,and a recovery phrase.
The NEAR explorer page for my account is
Instead of a hash for an ID,as in most blockchains,you get an actual string name.And the system can optionally do account recovery over email or phone.While this is convenient, it seems suspiciously centralized for a public blockchain,and I wonder if it is possible to create accounts without any central authority.I imagine it is, and this website is mostly a convenience, but don’t know yet.
Following the docs, I install
near-cli, a Node app.
Semes to work fine.
From previous doc reading I know that running a full node typically involves running nearup.It appears though that I don’t need that now,so probably for the purposes of developing on near,
near-cli will just talk to existing public nodes.
At this point I seem to hit the end of the “basics” documentation flow,without really accomplishing anything,but I remember from the beginning of these docs that “choose a starter project”is step 2.
I back up and choose the
rust-status-message starter project.
The examples say to install
near-shell,but that project has been renamed to
near-cli.I see that there are already PRs submitted to fix this,but they are about a month old.There are a number of relatively old PRs in NEAR repos that haven’t been reviewed.
I clone the example:
And build per the instructions:
package.json it’s true that npm isn’t doing much here,but it is adding a post-build step that cargo is incapable of:
There is an error in the build:
This is an easy error to understand to somebody familiar with embedded Rust development,but probably not to other newbies.The toolchain just doesn’t have the
wasm32-unknown-unknown target installed.I don’t know if I missed the documentation that explained this,but the user experience here could be better.
I add the wasm target:
After that the build works:
I try to deploy to the testnet using a temporary developer account:
NEAR wants me to opt in to telemetry.I’m sympathetic,but since this command presumably will have access to private keys,I’m not confident that the developers have been suitably carefulabout avoiding collection of private data.For now I say “n”, until I can review that code.
The command continues:
near dev-deploy has apparently created a script
neardev/dev-account.envthat will set the
CONTRACT_NAME environment variable to mytemporary account id,
dev-1599433413131-7008906.I call it with
near call to set the status message in the contract:
I browse to the provided testnet explorer address to see the transaction:
The transaction is already confirmed by the time I open the block explorer.That’s a nice change from Ethereum development.I wonder if the mainnet is so fast.
I note that the explorer is able to show me the contract arguments,
which is nice.
And the final step,I run
near view to query the contract’s message:
Seems everything worked pretty well.
Honestly,this has been a pretty refreshing experience compared to Ethereum onboarding.Besides the docs being a bit out of date,everything worked,and worked quickly.
The previous deployment used a temporary dev account.Per the docs,next I should use my real account that I created earlier,
I login to near cli with
So I have to visit a web page to authorize
near-cli to use my account,then come back here and enter the account name.
I open the web page and it’s a bit confusing. It says
is requesting full accessto your account.
This provides access to all of your tokens.
Proceed with caution!
Why is it “Unknown App”?
If I click “more information” then I see that the web site doesknow that this is for authorizing “NEAR CLI”:
This allows access to your entire balance. Please proceed with caution.
This allows NEAR CLI to:
The web page automatically fills in the name of the testnet accountI made earlier,
@floopy.testnet.I assume it is stored in a cookie.
I am not asked to enter any passwords,and come to think of it,I don’t have a password or private key that I know of,just a recovery seed,so I am curious about the security model.
I run into a problem:as part of the authentication flow,the testnet wallet website redirects me to a localhost HTTP address,presumably hosted by
I am running on an EC2 instance though,so this address is not accessible to me.
near login and look at its command line arguments to see ifI can have it listen on a different address.
It’s not obvious.
--walletUrl looks promising, though.
I try it, and that is not it.
--walletUrl is (obviously in hindsight)the address of
I am stumped.
For now I give up on seeing what’s at that localhost address,and hope I can complete authentication without it.I run
near login again,go back through the website authentication flow,then finally type in
floopy.testnet at the CLI prompt.
near login says
I guess it worked.
status_message.wasm using my
The transaction is on the block explorer here:
And again I call the
Everything works as expected.I feel a momentary lightness,as if I am having fun.I dare to think that maybe dapp development can be enjoyable.
rust-status-message docsI am going to proceed to set a status message for a second account.Seems like good NEAR practice to get used to juggling multiple accounts.
I create another account,this time from the command line.The
rust-status-message docs indicate the command for creating a new account is
It isn’t stated explicitly,but from the
--masterAccountswitch I take it that this command is for creating sub-accounts.The format of
NEW_ACCOUNT_NAME is not obvious,but I will assume it is
I try it:
The docs are out of date here too:the
create_account command is deprecated,and should be
I am confused by the text that says the account is for network “default”.What is the “default” network?I thought I was on the “testnet” network.
Anyway, the command seems to have worked.I haven’t been presented with any secret keys or recovery seed.I guess that’s all derived from the main account.
I try the
get_status calls with the subaccount:
This time I am calling the contract associated with the main account,
floopy.testnet,as the subaccount,
account2.floopy.testnet.Now the contract contains a status message for both accounts.
I can still retrieve the status of the original:
I am curious what the explorer says about the stateof the contract,whether it understands it enough to show methe two stored status messages.
The explorer page for
While that page shows reasonably-rich information abouttransactions against its contract,it doesn’t seem to show anything about thecurrent state of the contract.I might expect the data associated with a contract tobe self-describing enough to be displayed in the explorer.
The final instructions for the example are for running the contract’s unit tests:
--nocapture flag lets the Rust test runner print to the console,which in this case … does nothing.I guess the docs are again a bit misleading here.I wonder if there are any cases in which the NEAR SDK displaysuseful information from unit tests.
The code for this contract is contained in a single Rust source file:
It is surprisingly short.Small enough to reproduce the whole thing,sans unit tests,right here:
Not a lot of boilerplate,despite Rust being a general purpose language,not a purpose-built smart contract language like Solidity.
Some of the expected boilerplate is hidden behind
main function.Whatever mechanism this program uses to launch from NEAR’s WASM VMis hidden behind the
Curiously,there’s no indication this is a ‘no-std’ project,though it does use its own allocator,and,as far as I know,the standard library does not “just work” on the
I would expect to see a
#![no_std] attribute on the crate.I wonder if the standard library has been automatically pruned by virtue ofnot using any of its features.
wasm32-unknown-unknown is probably simply a no-std target:the standard library is never available.I wonder if this code can possibly compile for any targets other that
wasm32-unknown-unknown,not that it needs to.
Wow this code is really succinct.Except for the custom allocator,it’s pretty much all contract code,contract state in
struct StatusMessage,functions in
impl StatusMessage,no boilerplate.
borsh library used here is NEAR’s custom serialization library.
I notice the calls to
env::log('A').The logs output here show up in the blockchain explorer,as seen here:
I notice that the contract state is stored ina custom
UnorderedMap that is imported from
near_sdk,while the docs for this example say that the state isstored in a
HashMap.The docs probably do this for the simplicity ofnot explaining the SDK’s custom data types,but it’s a bit misleading.It’s probably not too confusing to say something more like,“status messages are stored in an
UnorderedMap,which is similar to the standard Rust
I note that the value returned from
env::signer_account_id() appears to be a
String,while I might expect it to be its own type.Might prevent some errors,though might make the code less succinct.
NEAR’s Rust contracts are unit-testable,and the SDK comes with a
MockBlockchain.That’s nice,since testing on a full devnet can be complex.I wonder if the unit tests are sufficient thatautomated testing on a devnet is unneeded,or if NEAR provides any help for automated testing on a live devnet.
The unit tests look like
Again this is nice and clean,but there’s something curious here:the
context is created and passed to a mysterious
testing_env! macro,but then never used again!What is it doing?Creating a thread local VM context?Seems potentially error-prone,though perhaps understandable considering that in a WASM environment,the runtime itself is a global resource.
I’ve reached the end of the
rust-status-message example docs,but feel I shouldn’t stop without doing some programming of my own.I’m going to make a change to the contract and deploy and test it,make sure I can write my own NEAR code and run it,end-to-end.
I add the obvious
remove_status(&mut self) method.To do so I need the appropriate method on
UnorderedMap,so I look in the near_sdk API docs.
The NEAR SDK is reasonably-well documented,though it could be better.There are no crate-level docs,and there are plenty of APIs without any docs.
The method on
UnorderedMap I need is
So I add this method to
Before I go through the build and deploy steps again,I wonder if I will be able to deploy a new contract to
floopy.testnet,overwriting the existing contract.
The sequence of commands I issue is:
Seems to deploy successfully.I learn that an account’s contract can be overwritten.
With a new contract,I expect the state will be cleared,and that if I call
get_status I will get an empty result:
OK, that’s interesting.
I (think) I have updated the contract for
floopy.testnet,but the previous contract’s state is still there,and is still compatible with the new contract.
Can I call my new
It appears that I uploaded a new contract with a
remove_status method,but that I actually did not,and that the old contract is still in place.
Something is wrong.
To double-check,I go through the build-deploy process again,and this time I get a different result.
This time,after deploying the new contract,I see that I no longer have a status message:
And I can set a new status message:
And finally call my new
remove_status to remove it again:
I’m confused about the inconsistent behavior.
I experiment some more,go through the build deploy cycle,with manual testing,numerous times.I can’t reproduce my original results,and have to assume it’s a problem with me and not NEAR.
Subsequent tests exhibit the following behavior:
Well, this is a confusing end to an otherwise painless intro to NEAR programming.Presumably things will become clearer with more experience.
Although there are quite a few blockchains that support Rust smart contracts,I originally picked NEAR for this experiment after noticingthat their documentation was surprisingly clear,in contrast to my experiences with other blockchains.
They’ve put a strong emphasis on the developer experience,and in my limited time here it shows.
When creating a platform for others to build off of,as programmable smart-contract blockchains are,it’s pretty important to make the developer experience as inviting as possible,and I think that is probably especially true in the blockchain space,where there is so much competition that it’s impossible to keep track of the options.
A good developer experience is important becausethe developers are your first adopters,the “thought leaders” who will advocate the product to the non-technical.If not a guarantee of success,at least a good developer experience can be the feature to set a product apart.
And so far I think that NEAR has a surprisingly good developer experience.
These are the issues I ran into during this experience.Team members might want to address these.Yeah, I should probably fix or file these,but hopefully at least listing them here is a useful gesture.
near-shell. Should be
rustup target install wasm32-unknown-unknown.
near create_accountcommand. Should be
--nocapture. It does nothing here.Does it ever do anything with NEAR unit tests?
HashMapbut they use a custom
near loginleads to a webpage that is authorizing an “Unknown App”.Should be “NEAR CLI”.
Rust Companion App Explained (FOR SETUP SEE FURTHER DOWN ARTICLE):
Pair with your Servers
Pair with your favourite Rust servers to receive real-time updates for the things that matter the most: player counts, current game time, online teammates, and more. You’ll also get (optional) push notifications whenever one of your teammates joins the game.
Explore the Map
View the full server map to find points of interest, see where your teammates are and check on vending machines. You can also track ongoing events like the attack helicopter and cargo ship.
Keep up with your Team
Communicate with your team from anywhere to just catch up or plan for your next raid. Messages are visible in both the app and the in-game team chat so you can seamlessly switch between the two.
Control your in-game Devices
Connect Smart Switches and Smart Alarms to your in-game electrical contraptions and pair them with Rust+ to control them remotely at any time. Smart Switches let you turn things on or off, and Smart Alarms send customisable push notification alerts when an electrical signal is detected.
For Further info: https://steamcommunity.com/games/252490/announcements/detail/2255687723359861140
Set up the Rust Companion App:
NOTE: If you purchased your server before 05 June 2020 - You need to perform a re-install from the 'Actions' Tab or this will not work.
Looking for a game server host known for brilliant 24/7 customer support and quality hardware?
Try a Pingperfect Rust server today! https://pingperfect.com/gameservers/rust-experimental-game-server-hosting-rental.php