Getting Started: Developing with Nano Currency — Part 3: Interacting with Programmable Software Wallets

SomeNano
SomeNano
Jan 30 · 21 min read
Image for post
Image for post

This post is part of a series of posts that help developers/coders/tinkerers of all levels get started coding with Nano (cryptocurrency).

  1. Build your foundation
  2. Interacting with Public and Private Nodes
  3. Interacting with Programmable Software Wallets [this article]

If you find any errors, contact me here on Medium (SomeNano), send me an email (jason@somenano.com), or find me on Twitter (@SomeNanoTweets).

Disclaimer: I link to many apps/frameworks/projects with which I have no association. While I have personally used every app/framework/project that I reference, I can not guarantee its security or availability. When in doubt, never use a “seed” or private key given from software you don’t know to be secure. Also, I have no association with the Nano Foundation and nothing in these articles should be taken as “Official” guidance. I am simply an advocate for Nano and want to support the Nano Community, and specifically those looking to code with Nano, as best I can.

Image for post
Image for post

Introduction

Hello again! You have made it to Part 3 of my “Getting Started” series on developing with Nano Currency! This series is giving you the essentials to write applications that interact with the Nano Network in various ways. While Part 1 of this series helped build your foundation of terminology and concepts and Part 2 of this series gave you an introduction to programmatically creating Nano Accounts, building Nano Blocks, and requesting Public Nano Nodes process them across the Nano Network, we are now going to go hands on and programmatically interact with a Programmable Software Wallet.

In this article I will briefly lecture on the concept of a Programmable Software Wallet and when/why you should use one. I will then showcase to you some open source Programmable Nano Software Wallets that are available free of charge. And we will then get coding and write a Nano Faucet web server application. Our web server application will demonstrate some key Programmable Software Wallet considerations and features. While our Nano Faucet web server application is a standalone example, we will be leaning on concepts explained and practiced in Parts 1 and 2 of this series. I highly encourage you to read and comprehend those articles before working through this article.

As we did in Part 2, you can load your Nano Faucet with Nano from a publicly available Nano Faucet. This, combined with the gracious open-source Programmable Software Wallet contributions from the Nano Community, will bring the total expense of this tutorial to… ZERO. And as always, sending Nano transactions on the Nano Network requires zero fees. So there is nothing holding you back from actually working through this tutorial for hands-on experience.

Now, before we really get started, I want to set your expectations appropriately.

This article is:

  • A lesson on the basics of how to programmatically interact with a Programmable Software Wallet.

This article is NOT:

  • A lesson in how to code
  • A lesson in secure coding practices
  • A lesson in key management
  • A lesson in browser security
  • A lesson in Node.js or web server security

Ok… onward!

When should I use a Programmable Software Wallet?

We learned in Part 2 of this “Getting Started” series how to go from “seed” to Nano Account to building Nano Blocks and processing Nano Blocks as “transactions” throughout the Nano Network. That said … you’ve done it all! There is no other functionality in the Nano Network. So why is there a Part 3 to this series?

Part 3 exists because it is the Software Wallet where the god-like attributes of the Nano protocol (speed, efficiency, feeless) interact with us mere mortals in magical ways.

As we discussed in Part 1, a Software Wallet (both programmable and non-programmable) typically accomplish at minimum five tasks:

  • Create a Nano Wallet
  • Create one or more Nano Accounts
  • Send Nano
  • Receive Nano
  • Change representative
Image for post
Image for post
Nano Software Wallet Workflow (from Part 1)

Wait, aren’t these the same tasks that we accomplished in Part 2 of this series? Well look at that, it seems as though we coded up our own Software Wallet! And that’s the point I want to make. A Software Wallet simply abstracts the tasks of building Nano Blocks and managing your Nano Account(s) to a higher level.

When interacting with a Software Wallet, we typically are not ever going to build a Nano Block from scratch. We do not need to know what value the link field represents. We don’t need to know that there is a difference in the work value based on whether the Nano Block is a send, receive, or change subtype. We let the Software Wallet do that for us.

So when should you use a Programmable Software Wallet? You should use a Programmable Software Wallet when you don’t want to spend your coding time in the weeds building Nano Blocks. If you are fine with the five tasks listed above, then working with an existing Programmable Software Wallet is likely the right entry point for you.

So where is the magic? The magic is in the implementation.

Whether you are using a plain send/receive Programmable Software Wallet to build an application like a Faucet (as we will later in this article) or you are abstracting another Software Wallet with unique and innovative features on top of it (anonymity? mixing? payment processing?), this is where that magic is showcased.

Open Source Programmable Software Wallets

The list of existing open-source Programmable Software Wallets (which I will from here on out simplify to Software Wallet) is actually not that long. I think this is due to two reasons:

  1. The Software Wallets that do exist already are robust.
  2. Many developers build their applications from scratch and implement their own homemade Software Wallet (as we did in Part 2). Implementing their own solution is potentially more secure as the developer has complete visibility of the solution and is really not that difficult.

In this article, I will highlight two Software Wallets, first the Software Wallet that is built into the Nano Foundation’s Nano Node. And then I will introduce and dive much deeper into the Pippin Nano Wallet.

Nano Node Software Wallet

The Nano Node Software Wallet is feature-rich and “for development and testing only”. It comes baked in with the Nano Node. So if you already have a Nano Node running, you already have a Software Wallet available to you. If you are relying on a Public Nano Node, however, these Software Wallet RPC actions will not be made available to you.

As this Software Wallet comes with the “development and testing only” disclaimer, and there are other options, this is as far as we’ll go in this article with the Nano Node Software Wallet.

Pippin Nano Wallet

Image for post
Image for post

The Pippin Nano Wallet (brought to you from the same dev as Natrium) is a self-proclaimed “production-ready, high-performance developer wallet”. I won’t regurgitate the benefits of Pippin or the performance specs of Pippin here, however impressive, as they are well explained in the links. But I will say that Pippin offers nearly the same set of RPC actions that the Nano Node Software Wallet offers. The actions it leaves off, I have never needed. And the actions it adds, I have used extensively.

The feature that I love most about Pippin, though, is its ability to operate remotely from a Nano Node. This is important to me for two reasons:

  • If I am new to developing with Nano, I can use Pippin and a Public Nano Node (no Nano Node install/maintenance required).
  • If I am running my own Nano Node, I can allow the Nano Node all the resources it requires without much consideration to any other applications.

This here is the easiest way to begin developing with Nano. I wish I could better highlight this fact. A Pippin install connected to a Nano Public Node (which we will do in this article) gives an extremely simple API to begin transacting Nano in minutes. Please, however, do take note of my previously mentioned security considerations when interacting with a Nano Public Node.

Hello, Pippin!

The Pippin Wallet is written in Python and is available via pip. Similar to the background on Pippin, Appditto (the dev of Pippin), provides great install instructions across multiple platforms.

Where I want to begin, for our specific implementation exercise, is post-install. Let’s talk configuration.

If you are following along from home, you just arrived at the Configuring Pippin section of the docs and have just run pippin-server --generate-config to generate a sample config file in ~/PippinData/. Go ahead and rename this file to the actual config cp ~/PippinData/sample.config.yaml ~/PippinData/config.yaml and open it up in your favorite editor.

Configure Pippin

Make the following changes to the config (I am only showing lines that I have modified, do not change where each line is located in the file):

  node_rpc_url: https://nault.nanos.cc/proxy
node_work_generate: true
receive_minimum: 1000000000000000000000000000
auto_receive_on_send: true

Let’s quickly review each line.

Under node_rpc_url, we are identifying the Public Nano Node with which the Pippin Wallet will be communicating. Any Public Nano Node would work fine. However, make note if a Public Nano Node does not support work_generate. If that’s the case, you must set node_work_generate to false (default) and compute work on your server, which is likely slow.

As mentioned above, under node_work_generate, we are telling Pippin to outsource the computation of work values to the Nano Node we identify under node_rpc_url.

The receive_minimum value will tell Pippin what value of raw (a unit of Nano) we want to receive automatically. Setting this value will combat spam. As mentioned in Part 1 of this series, you can send as little as 1 raw on the Nano Network. It may not be worth your time to receive a transaction of 1 raw if you have a busy wallet. If this is the case, set this value accordingly. In this example, the value is set to the equivalent of 0.001 Nano.

Last but not least is one of those features that I really like in Pippin. It is the auto_receive_on_send configuration. If true, your wallet, when attempting to send Nano and the balance is not enough, will automatically receive all pending transactions, if adding the balance pending results in enough of a balance to support the send. For example, you have a balance of 0.15 Nano and a balance pending of 1.6 Nano across multiple pending Nano Blocks. If you attempt to send 1.0 Nano and auto_receive_on_send is true, then your pending Nano Blocks will be received first, resulting in a balance of 1.75 Nano, then the send will execute taking your balance to 1.65. Be forewarned, though, all pending Nano Blocks (with amount greater than receive_minimum) will be received. If this is a large number of Nano Blocks, your send action might take longer than expected.

One configuration that I did not set and you might be tempted to set is the node_ws_url line. Setting this value will enable your wallet to automatically receive pending Nano if the value of the transaction is greater than receive_minimum. It is a nice feature and will likely ensure a send action isn’t delayed while waiting on the auto_receive_on_send action. However, as we are using Public Nano Nodes in our example, you must know that the WebSocket server you put on this line must support subscribing to confirmations without setting any constraints on Nano Addresses in the options. Many of the Public Nano Nodes (mine included) run the Nano RPC Proxy which (by design) does not support the potential firehose of all confirmed Nano Blocks with no constraints on relevant Nano Addresses. So that’s simply my public service announcement. There do exist Public Nano Nodes that support subscribing to all Nano Block confirmations, but it is not necessary for this article, so I do not set it. If you do set a WebSocket server that does not support, Pippin will alert you on start.

Start Pippin

Running the Pippin server is as simple as running pippin-server. You can build a service to manage/keep running the Pippin server, however, for our purposes here, simply running from the command line will work fine.

Once Pippin is running you can check for a good connection by running:

$ curl -g -d '{"action":"block_count"}' localhost:11338
{"count":"66020255","unchecked":"1","cemented":"66020255","requestsLimit":"5000","requestsRemaining":"4997","requestLimitReset":"Thu Jan 28 2021 18:51:10 GMT+0000 (Coordinated Universal Time)"}

Calling the block_count action will not only ensure you have a good connection to the Pippin server, but it will also ensure that Pippin has a good connection and is communicating with the Nano Node you set in the config as node_rpc_url.

If it errors out, check to make sure you are targeting the correct port as listed in the config.yaml file. You can also check to make sure your machine is listening on that port. For a Linux server (I am running Ubuntu 20.04.1 Server for this tutorial) you can run the command sudo netstat -tulpn | grep LISTEN to view all listening ports.

$ sudo netstat -tulpn | grep LISTEN
tcp 0 0 127.0.0.1:11338 0.0.0.0:* LISTEN 12473/python3

And lastly, you can always check the Pippin logs. The location of the logs is set in the config under the log_file line. Default is /tmp/pippin_wallet.log.

Build a Nano Faucet

Now it is time to get coding!

To demonstrate the capabilities of a Programmable Software Wallet, Pippin in this article, we are going to code a Nano Faucet. A Nano Faucet is a location that people can go and collect some amount of Nano for free. There exists multiple Nano Faucets around the Internet already. Here are a few reasons we are going to create a Nano Faucet in this article:

  • It demonstrates simple API calls to the Pippin server.
  • It demonstrates Pippin server’s seamless integration with a Nano Node.
  • It showcases the differences between running a Software Wallet on a server versus a client.
  • You will be introduced to the concept of idempotency.

Server vs Client Software Wallet

In Part 2 of this series we coded the functionality of a client Nano Software Wallet. In this part of the series we are using the capabilities of a server Nano Software Wallet. The main consideration you want to take when deciding whether to use a client or server Software Wallet is who owns the seed.

If a user of the application controls the seed, then there is no reason for the server to ever become privy to the seed, and that means a client Software Wallet is the way to go.

If you, the server operator, control the seed (as is the case in our Nano Faucet), the seed should remain on the server and users of the application should never become privy to the seed, then a server Software Wallet is the way to go.

Image for post
Image for post

This is a design decision that needs to be made at the beginning of your application development. Whenever possible, the client should maintain its own seed (non-custodial wallet). There are few instances where a server should be managing a user’s seed (custodial wallet). In our Nano Faucet example, however, the faucet is not a wallet for use by the user. We (the operator of the server) are the user and using Pippin as a non-custodial wallet.

Setting up the Nano Faucet

First I will walk you through running the Nano Faucet. And then, following, I will walk you through the code that built the Nano Faucet.

You can find the code for this tutorial on GitHub.

$ git clone https://github.com/somenano/Tutorials
$ cd Tutorials/GettingStarted/Part3
$ npm install

At this point we have:

  1. Installed Pippin as our Software Wallet
  2. Configured Pippin to communicate with a Public Nano Node.
  3. Downloaded our tutorial code and installed its dependencies.

If you attempt to run the Nano Faucet code at this point you will see it fails and you are shown additional instructions.

[Alert] You must set your Pippin Wallet ID in the .env file as PIPPIN_WALLET=

Our Nano Faucet application needs to be configured with a Pippin Wallet.

To create a new wallet in Pippin, you can either issue the command via the wallet_create RPC or via command line. Note that I am using the Nano Node Software Wallet references in most of my Pippin command references. This is because, with few exceptions, they are the same.

If you wanted to programmatically create wallets during runtime of your application, RPC would be the way to go. But as our Nano Faucet will contain exactly one wallet and one Nano Account, we will simply generate the new wallet and Nano Account from the command line.

$ pippin-cli wallet_create
Wallet created, ID: b2e322b5-90e8-4c84-b6f2-245e4a75d773
First account: nano_3ho7jmrqucfckark7honprah49r597wbpqcjgnr53t7d6xhoc54cybibnz5z

Your “Wallet ID” and “First account” will be different than what I generated above. Now that we have the information, go ahead edit the .env file to enter the information.

PORT=3000
FAUCET_PAYOUT=10000000000000000000000000000
VERBOSE=true
PIPPIN_SERVER=http://localhost:11338
PIPPIN_WALLET=b2e322b5-90e8-4c84-b6f2-245e4a75d773
NANO_ADDRESS=nano_3ho7jmrqucfckark7honprah49r597wbpqcjgnr53t7d6xhoc54cybibnz5z

If you need to view your wallet information again later, you can view it by running:

$ pippin-cli wallet_list
ID:b2e322b5-90e8-4c84-b6f2-245e4a75d773
Accounts:
nano_3ho7jmrqucfckark7honprah49r597wbpqcjgnr53t7d6xhoc54cybibnz5z

Also at this point you want to back up your seed:

$ pippin-cli wallet_view_seed --wallet b2e322b5-90e8-4c84-b6f2-245e4a75d773
Seed: BDE5A3A.......

Running the Nano Faucet

Everything is now in place, start the Nano Faucet application:

$ node server.js

Once the Nano Faucet application is running, you can access it at http://localhost:3000.

Image for post
Image for post
Initial view of our Nano Faucet

The first thing our client page (index.html) does is send GET request to /info.

Image for post
Image for post
GET /info returns JSON formatted info about our Nano Faucet

Navigate to http://localhost:3000/info in your browser and see what information is being returned (can also view in your browser’s console). This information, once it it retrieved, is displayed on the Nano Faucet webpage. If you do not see this information, check the output from your node server.js. And if you don’t see anything thing, you can check the Pippin logs as mentioned earlier in the article.

Once you have confirmed that the server is up and running, click the Nano Address on the webpage to view your Nano Account on NanoCrawler.

Image for post
Image for post
View your Nano Account on NanoCrawler

You can fund your faucet by scanning the QR Code with an app like Natrium and sending some Nano to it. Or you can head over to any of the existing Public Nano Faucets and paste your Nano Address there to get funded.

Take note that the default payout of our Nano Faucet we are creating is 0.01 Nano. If you use a Public Nano Faucet, you may not receive enough Nano to fund a payout at this level. You can change the payout amount in your Nano Faucet by updating the FAUCET_PAYOUT value in the .env file. The value in the .env is in raw, reference nanoo.tools for a simple tool to convert the unit Nano to raw.

Image for post
Image for post
Easily convert units from NANO to raw

After you send the initial funding to your Nano Faucet, you should see the amount listed as “pending”

Image for post
Image for post
Nano balance is pending

If you set up the node_ws_url in the Pippin config earlier, you might not see a balance pending as Nano and Pippin are super fast. By the time you refresh the page Pippin might have already accepted the pending balance into your Nano Account.

But if you did not set up node_ws_url (as I did not) you will see a balance pending. And the handling of this balance pending is one of the phenomenal features of Pippin that I want to highlight. In our configuration of Pippin we set auto_receive_on_send: true. This means that we don’t have to listen to a WebSocket for pending Nano Blocks. And we don’t have to periodically check for pending Nano Blocks nor manually receive them. When we issue a send action to the Pippin wallet, it will:

  1. Recognize that our balance is too low to complete the send.
  2. Check for any pending Nano Blocks that it can receive to fulfil the send amount.
  3. Create the necessary Nano Blocks of subtype receive to increase the available balance.
  4. Create the Nano Block of subtype send to complete the action.

Like I said, the Software Wallet is where the magic happens!

So let’s see this in action. Let’s copy our Nano Faucet address and make a payout to ourselves.

Image for post
Image for post
Nano Faucet after first payout

The hash of the Nano Block is returned and shown as a link. It can be clicked to view the Nano Block on NanoCrawler. Also, once the hash is received, the website makes another GET request to /info and updates the Nano Faucet information. You will see (and can confirm on NanoCrawler) that:

  1. The balance pending (0.1 Nano in my example) was received by the Nano Account
  2. A Nano Block of subtype send (0.01 Nano in my example) was created
  3. The Nano Account now has a balance pending of 0.01 Nano. This is the send from #2 that is not yet received by the Nano Account. See the same referenced hash values?
Image for post
Image for post

If you received an error and not a Nano Block hash, check your browser’s console for details on the error. If your Nano Account did not receive the balance pending, you might need to compare the value of the balance pending and the value you set in the Pippin config (~/PippinData/config.yaml). In our example we set the receive_minimum to 1000000000000000000000000000 raw (0.001 Nano). So if you sent less than that amount (either from a Public Nano Faucet or your own wallet), you will need to decrease the receive_minimum value and restart Pippin in order for Pippin to receive the pending Nano.

And that completes our initial walkthrough of running and using the Nano Faucet. Now let’s dig into the code where we’ll learn more about how the Nano Faucet operates.

Coding the Nano Faucet

For this section I will not be going through every line of code. I will highlight certain blocks of code and will note certain considerations you will want to make while building future applications with Pippin or other Programmable Software Wallet.

Also, just a note, while writing this article, I have realized there is no good way to embed code snippets from a GitHub repository in a Medium article. So I’ve resorted to screenshots. I’ll apologize in advance if I make updates to the GitHub repository and not all changes make it to the screenshots in this article.

Beginning in server.js:

Image for post
Image for post
Nano Faucet pippin_post function

First we’ll start with the function that handles all communications with the Pippin server, pippin_post. Nothing much to see here, though. We are using axios to handle our POST requests.

Image for post
Image for post
Nano Faucet send function

The send function is a wrapper for Pippin’s send action. There are a few items worth mentioning here. As with all Nano Node RPC actions, the amount here is in raw units. Also, I do zero input validation here. Input validation will likely depend on your implementation and how/where you want to handle invalid inputs. For this Nano Faucet I rely on Pippin to validate inputs. If there is invalid input, JSON will be returned to the Nano Faucet application and be forwarded on to the client with an error key.

And lastly for send I want to talk about the id key. This is important. The id key is a string that will ensure a particular send action is only executed once. This combats a potential replay attack. An id may only be used once. Per the Nano Node Software Wallet docs, if an id is used more than once, the Nano Block hash of the original send will be returned (no extra send executed).

Let’s demonstrate this concept. If you worked through the “Running the Nano Faucet” section above, you will have completed a payout to your faucet’s own address. Go ahead and request another payout to that same address. See what happened? The hash that is shown is the exact same hash as was returned for the initial send. And no additional payouts were made. This is because in our Nano Faucet, we are using the payout Nano Address as the id (more below in the /submit handler). So no Nano Address can use the faucet more than once.

Image for post
Image for post
Nano Faucet account_balance function

The account_balance function is a wrapper for the Nano Node’s account_balance action. Note that I said “Nano Node” and not “Pippin”. The account_balance action is a Nano Node RPC, not a Software Wallet RPC. But Pippin will receive and forward Nano Node RPC actions to the Nano Node you defined as node_rpc_url in the Pippin config. This allows you as a developer to communicate solely through the Pippin server.

Image for post
Image for post
Nano Faucet /submit handler

The /submit handler is what handles the request for payout from the Nano Faucet client. It receives one URL parameter of destination.

Now here is where we have some missing logic. If we were to make this Nano Faucet publicly available, it would be abused and emptied VERY quickly. This is because the only check we have in place is to send payouts to a single address no more than once. You can see the second argument of send is destination. That is the id field. So that is where we are ensuring only unique Nano Addresses are receiving payouts. However, it is trivial to create multiple Nano Accounts and someone could quickly make thousands of requests to our Nano Faucet from unique Nano Addresses.

Defending against faucet abuse is both an art and a science. I won’t delve much deeper because this is a tutorial on interacting with Software Wallets and not on the finer details of developing a Nano Faucet. But some considerations you would likely want to take are: IP reuse, captcha requirements, and browser fingerprinting.

Image for post
Image for post
Nano Faucet /info handler

And finally the last code block that we’ll cover for server.js is the /info handler. This function simply makes an account_balance request and returns JSON to the client with balance information as well as faucet information.

Now, onto the client side in index.html.

Image for post
Image for post
Nano Faucet get_request function

The get_request function handles the networking between the client and the server. It takes three arguments, theUrl for the path, callback for a function pointer to be called with the returned JSON from the server when the request is successful (HTTP 200), and callback_error for a function pointer to be called with the response object when the request is other than HTTP 200.

You can see implementations of the get_request function in the below code blocks.

Image for post
Image for post
Nano Faucet refresh_faucet_info function

Here in the refresh_faucet_info function is where the client makes a GET request to the /info endpoint on the server. Most of the code is simply parsing data and having it displayed on the webpage. You will see some familiar code from Part 2, though. The NanoCurrency object (from the nanocurrency package) is being used to convert units from raw to Nano.

If I were hosting this Nano Faucet publicly, I would likely lean on the nanocurrency package a bit more on both the client and server, especially for input validation. The package has a robust set of validators for things like Nano Addresses and Nano Block hashes.

Image for post
Image for post
Nano Faucet form_submit function

The form_submit function is similar to the refresh_faucet_info function in that it makes a request to a server endpoint, /submit in this case, and handles the response, updating the webpage.

This function is where you could add some client side validation, in addition to your server side validation, for appropriate use of the Nano Faucet.

Conclusion

And that’s it! In this article we…

  1. Discussed when it is appropriate to use a Programmable Software Wallet
  2. Introduced some open source Programmable Software Wallets
  3. Installed and configured Pippin Wallet
  4. Built and ran a Nano Faucet integrating a Pippin as a Programmable Software Wallet

As a final capstone and comprehension test of what we’ve covered I’ll give you a challenge.

Write an application that will receive Nano to a unique Nano Address and then consolidate all received Nano into a single Nano Address. This will behave as many payment processors do (ex: Payment is complete when a pre-defined Nano Address receives a certain amount of Nano. Once payment is confirmed, the Nano is forwarded to a set “savings” Nano Account).

I want to thank you very much for reading this article. I hope you found it useful as you begin developing with Nano. It really is a phenomenal technology and a lot of fun to dig into and build with.

I have linked many references throughout this article and I hope you do decide to dig deeper.

This does conclude the “Getting Started” series and I hope you found it not just useful, but inspiring and motivating. Review the articles as you need and I will do my best to keep them current as time progresses.

  1. Build your foundation
  2. Interacting with Public and Private Nodes
  3. Interacting with Programmable Software Wallets [this article]

While you are here on Medium, I recommend you also read articles from Nano Education, Nano, and the Nano Publication. If you are on Twitter, feel free to follow me @SomeNanoTweets. If you are on reddit, Nano has a phenomenal subreddit with a huge amount of helpful and highly intelligent people. And if you are more of a real-time chat sort of person, check on the Nano discord where there is a specific dev channel to help aspiring Nano “BUIDLers” like you and me.

~ SomeNano

Ps, these articles are a lot of fun to write but they take A LOT of time. I wrote it to support Nano Community developers. And I would be highly appreciative if you also consider supporting me in return. If you found this article useful, please consider sending a donation.

Image for post
Image for post
nano_1somenanerzdzdbyr4y6x996qbo764ifxk8beuhphydmwn1agpzkwquqqick (NanoCrawler link)

Nano

The best place for all of the latest Nano updates…

SomeNano

Written by

SomeNano

BUIDLing with Nano since 2017

Nano

Nano

The best place for all of the latest Nano updates, developments and interviews. Brought to you by the Nano Foundation.

SomeNano

Written by

SomeNano

BUIDLing with Nano since 2017

Nano

Nano

The best place for all of the latest Nano updates, developments and interviews. Brought to you by the Nano Foundation.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store