Image for post
Image for post

Kadena Public Blockchain: Getting Started with Transfers

Emily Pillmore
Dec 19, 2019 · 16 min read

Kadena began enabling Kadena (KDA) token transfers on December 17. The network has experienced some serious growth as we’ve transitioned from testnet to mainnet, with over 1,000,000 blocks mined by more than 10,000 GPUs (at an average hash rate between 10–15 TH/second) on mainnet. We’ve been heavily relying on the community to help establish best miner practices in the network.

Now, tokens earned by miners are transferrable to and from other accounts (peer-to-peer). Because transfers are such an integral part of any blockchain ecosystem, we’ve decided to publish this post as an introduction to the Pact smart contract system. We’d like to illustrate the myriad ways to transfer tokens and highlight some of the technologies available to users to do so. We’ll break down this tutorial into three steps of varying levels of sophistication: using Pact to create a smart contract, the standalone transfer portal, and transferring with the Chainweaver Wallet.

Hopefully, this will get you excited to begin your journey with Kadena. Let’s get started!

The Kadena Coin Contract

Kadena’s coin contract was made available as a transaction at genesis, which means the token is a contract in the same way that any other contract exists in the blockchain (though, it is somewhat special with the way each Chainweb node interoperates with it natively). While we don’t yet have a module explorer for people to browse module code (coming soon when smart contracts are turned on), you can browse the source and the Kadena Improvement Process (KIP-0002) RFC for the fungible asset token (KDA) on which it’s based to get a feel for both the Pact language and the fundamental operations available in the contract. Most notable among these are the specifications for how to transfer KDA to and from accounts on the blockchain. We’ll go through the accounts and the types of transfers available to you in the next few sections, and then move on to a tutorial for how to actually put transfers into practice along with some of the available tools.

How are Kadena Accounts Structured?

We’ve written up a Beginner’s Guide to Accounts in the Kadena blockchain, but let’s do a whirlwind tour here just to refresh. The Kadena blockchain is unique in the sense that each chain is a separate blockchain for which a global consensus is maintained, and there is no global notion of “account” or “address.” On each chain, however, there is a keyset registry that makes sure that no keyset gets duplicated. This means that the final decider for what uniquely identifies a user of the blockchain is their keyset on a given chain (read here for more on keysets). If you choose to have your keyset only exist on chain 0, that’s your prerogative and perfectly fine. However, users may find it simplifies things if they define their keyset on all chains to avoid confusion, even though there’s a cryptographically nil chance that anyone else might have the same keys on a different chain.

Every smart contract has the ability to maintain its own ledger (a key-value store) that defines the data structures it works with. In the case of the coin contract, every entry into the coin contract ledger is specified by an account name (any LATIN-1 string between 3 and 256 characters) as a key, with a value of both a decimal balance and a keyset that governs the account. Account names can be anything as long as they conform to that spec. You could be "emily", "stone cold steve", or simply the public key associated with your keyset as an account name. Many users find the latter to be the easiest to remember. Since the chance of overlap is negligible, it helps them remember which keys they’re supposed to use for that particular account. I support this, as the two accounts "emily" and "Emily" are distinct and it can be easy to forget which is yours. We call accounts that are not simply the public key string “vanity accounts” (like vanity license plates), to distinguish naming conventions.

So, to summarize,

key: Account name -> value: { Balance, Keys }

It’s that simple! Now, let’s talk about the types of transfers available with this token.

Types of Available Transfers

I’ve shown you how to construct a simple coin transfer, but now let’s talk about the types of transfers available to you, the user. The coin contract has 3 in total to address varying use-cases:

  • coin.transfer: This function is for transfers between two existing accounts on the same chain, for some decimal number of tokens. This is the one I showcased above, and is the most basic of the transfers. It works exactly as you might imagine.

Smart Contracts with Pact

Pact is the smart contract language running at the heart of the Kadena public blockchain. We’ve produced a bunch of tutorials on every aspect of the Pact language ecosystem, but we’ll review a few here to illustrate our use-case. This will be done with Pact 3.3, the currently available version of Pact.

Creating an API request

Smart contracts are written in Pact. To actually get them into a block on the blockchain, they need to be sent to a blockchain node. This is done by formatting an API request and sending the request to the appropriate endpoint. Pact has this functionality built into the language in the form of the pact -a family of commands. To make use of pact -a, one must create an API request template that takes the form of a YAML script pointing at (or containing) Pact code, which is then converted into the appropriate JSON representation. A user may then submit this JSON in a cURL request (or e.g., a Postman request) to the blockchain for processing.

For example, if I wanted to transfer 1.0 KDA from my vanity account, emily to nick-cage because I’m such a huge fan, I would construct a YAML template request like the following (note: using a burner keypair generated by pact -g for demonstrative purposes):

Image for post
Image for post
Nick Cage boutta be stoked

This looks complicated. Unfortunately, it is, which is why we automate this all in the wallet. All you have to do is toggle the knobs with whatever is appropriate. However, it’s still good to know about what settings you’re able to toggle to achieve an optimal transaction specification. The anatomy of this request can be broken down as follows:

  • (code|codeFile): This field is either the raw code you wish to execute or a reference to a .pact file containing the smart contract you wish to execute.
Math.round((new Date).getTime()/1000)-15;
  • networkId: This field describes the ID of the receiving network. Since Pact is blockchain-agnostic, this may be Tendermint, or Polkadot, or any of the myriad blockchains supported or to be supported in the future. Currently, the network ID for the main Kadena network ismainnet01, but through this tutorial, I’ll be running on testnet04 to make sure no actual transactions go into the main blockchain.

For a more complete specification of the available options, consult the Pact API Request Formatter documentation and the tutorials on pact-lang.org. Here’s a template that can be copied and pasted for your requests:

code:
data:
networkId:
publicMeta:
chainId:
sender:
gasLimit:
gasPrice:
ttl:
creationTime:
keyPairs:
- public:
secret:
caps:
type: exec

And here’s the one I used that you can cargo cult for yourself and change all of the bracketed fields:

code: |-
(coin.transfer <from> <to> 1.0)
publicMeta:
chainId: "0"
sender: <from>
gasLimit: 600
gasPrice: 0.0000001
ttl: 600
creationTime: <regenerate this>
networkId: "mainnet01"
keyPairs:
- public: <public>
secret: <secret>
caps:
- name: "coin.TRANSFER"
args: [<from>, <to>, 1.0]
- name: "coin.GAS"
args: []
type: exec

Once I have this YAML file all figured out, I generate the following JSON request using pact -a and passing in the YAML file as a parameter:

Image for post
Image for post
Nick Cage waits impatiently…

Now, I have a JSON object that I can post to the /send endpoint of the Pact Service API for the Kadena blockchain. In practice, this will be a POST request with the formatted JSON object on a node endpoint which takes the following form: https://<host>:<port>/chainweb/0.0/<network-id>/chain/<chain id>/pact/api/v1/send. Here is an example cURL request that I’m using:

curl --location --request POST 'https://us2.testnet.chainweb.com/chainweb/0.0/testnet04/chain/0/pact/api/v1/send' \
--header 'Content-Type: application/json' \
--data-raw '{"cmds":[{"hash":"F7jzCyUgwcBUWYVe3xEFw66X45NHgheNrqm8LL9gMIU","sigs":[{"sig":"c0024309593b8b28b356c5edfed957c1dd7e163eecc446a327fa8d4db76faccc111b11786fe9cc6fc200ceab137d53f4df46ab76aa7f268be183289f282db20e"}],"cmd":"{\"networkId\":\"testnet04\",\"payload\":{\"exec\":{\"data\":null,\"code\":\"(coin.transfer\\n \\\"emily\\\"\\n \\\"nick-cage\\\"\\n 1.0)\"}},\"signers\":[{\"pubKey\":\"368059ab25bec92f19a4f8ce172030e5d672e4879aaae8d5be8b705dd3dfae7f\",\"clist\":[{\"args\":[\"emily\",\"nick-cage\",1],\"name\":\"coin.TRANSFER\"}]}],\"meta\":{\"creationTime\":1576691834,\"ttl\":600,\"gasLimit\":100000,\"chainId\":\"0\",\"gasPrice\":1.0e-7,\"sender\":\"emily\"},\"nonce\":\"2019-12-18 17:58:40.212918 UTC\"}"}]}'

When the blockchain has accepted your request, you’ll get a request key back — the unique key associated with your request as it’s processing.

Image for post
Image for post
Nick Cage is on the edge of his seat

To see the outputs of your transaction, POST that request key JSON object to the /poll or /listen endpoints. When the transaction has been mined and exists in some block, you’ll get a response back. Note that it may take a few block heights (i.e. 30–90 seconds) to see your transaction, and you will not receive outputs during that time. Here’s an example of a /poll cURL request and the response:

curl --location --request POST 'https://us2.testnet.chainweb.com/chainweb/0.0/testnet04/chain/0/pact/api/v1/poll' \
--header 'Content-Type: application/json' \
--data-raw '{
"requestKeys": [
"BYHjcdTqqMTROLasn82ka-DpYhE9Q1K3nFxt5vcXxGQ"
]
}'
Image for post
Image for post
Nick Cage just got paid!

Success!

We realize that this is a low-level technically intensive process, but like every API on the web, there exist tools that automate this experience and provide varying levels of sophisticated UI to help make the process seamless. We’ll get into these tools below, but first, let’s talk about dry-running transactions to make sure that they succeed.

Using /Local to Dry-Run Transactions

The Kadena blockchain follows the example that Ethereum set by charging the gas limit specified in a transaction in the case that the transaction fails. This takes place for a few very important reasons:

  • It incentivizes users to only submit transactions they know will succeed, or get penalized. This closes a serious DOS vector for node operators.

On its own, this would be a rather punishing system. After all, it is inevitable that new users will be unfamiliar with how to transact with the blockchain. And even more so inevitable that people make mistakes when transacting. To provide as much information as possible, every Kadena node has a dedicated endpoint called /local on which a user can dry-run their transactions and discover the costs and outputs of a given transaction.

As mentioned above, pact -a is a family of commands. The command that generates a valid local request is pact -l -a, and can be used with any existing request YAML to produce a JSON object compatible with the /local endpoint of any node. Chain ID does not matter in this case — the endpoint will accept any valid command — but it’s good to provide accurate information to produce valid feedback for the dry run. As above, we’ll reuse the existing transfer request from "emily" to "nick-cage":

Image for post
Image for post

Now, let’s submit this to pact -l -a. This will generate the following JSON object:

Image for post
Image for post
Nick Cage is getting locally stoked

Then, let’s send this to the /local endpoint. This time, rather than receiving a request key, we receive the outputs directly along with some additional metadata not included with the outputs of a /send transaction:

Image for post
Image for post

The outputs display the results, the logs, a request key, all of the metadata used in the transaction, along with the most up-to-date block time, parent block hash, and block height on that chain. Not only do you know if your transaction will succeed, but you’ll have all the context you need to figure out why it failed. Let’s see what failure looks like in this mode by using a user that does not exist as the recipient of our transfer:

Image for post
Image for post
Lol he is definitely not Nick Cage

Our recipient, “Lol I am definitely not Nick Cage,” does not exist in the blockchain, and so I’ve received confirmation that my transaction failed. This information is sent along with the callstack, type of error, specific failure message, and wherein the coin contract the code that called it failed.

Tools for Transfers

As mentioned above, there are a few tools available to you that automate the construction of API requests (and transfers in particular). They are available in a few different forms.

Community Transfer Scripts

There is a standalone community transfer script which automates the construction of transfers by providing web fields which fill in the necessary information for your API request and call our Pact Lang Javascript API which sends the transactions for you:

Image for post
Image for post

You can either set this up in your browser by using the index.html provided, or you can run it as a standalone script with node as described in the README.md of the project. If you read the first section thoroughly, it should all be very familiar, and you can picture how the YAML is being created and sent via this information. However, you’ll see that there’s a lack of gas and TTL/creationTime. That is because we’ve chosen some sensible defaults that should make the process even easier. This script will run a coin.transfer or coin.transfer-create depending on the parameters you supply. Pool operators and power miners such as BigShoots have set this up on their nodes as a courtesy to other users (thanks BigShoots).

Chainweaver Wallet

If you’re on Mac or Linux, you can make use of Kadena’s in-house Smart Wallet offering: the Chainweaver Wallet.

The Chainweaver Wallet features a full Pact IDE (including a REPL) for authoring smart contracts and interacting with existing smart contracts on the Kadena blockchain in addition to its account servicing features. I recommend you run the wallet from the perspective of a smart contract writer (and, for transparency, a Kadena employee).

Image for post
Image for post
Chainweaver Accounts
Image for post
Image for post
Beautiful isn’t it? This is the Pact IDE embedded in the wallet

Chainweaver has a great UI for sending and receiving tokens using a novel address format for Chainweaver users that we are calling a Kadena Address. In the Wallets tab, locate your Chainweaver account and simply click the “send” tab, which will take you into a small popup window in which you can paste the Kadena Address of the receiving account. Depending on the context, Chainweaver can detect whether a particular receiving account exists and on what chain, and will choose whether to use coin.transfer, coin.transfer-create, or coin.transfer-crosschain depending on that context. It will even automate the previously manual step of constructing an SPV proof in the case of a cross-chain transfer. We’ve written up a thorough tutorial to help you understand all of the snazzy features available in Chainweaver.

Additional Wallet Options

We welcome any wallet additions as community projects and will be happy to help set you up with a dedicated repository in our Kadena Community GitHub organization if you have a submission. There is one already, courtesy of our Kadena’s Colin Woodbury (@fosskers). He wrote a fantastic CLI wallet aptly named Bag of Holding, which you can operate from your terminal:

Image for post
Image for post

Bag of Holding works essentially as a nice UI around the creation and execution of API requests as described earlier in this article. It’s solid, simple, reliable, and (I think) looks great.

Conclusion

There you have it: an introduction to Pact transactions by way of transfers. Our tooling is in the very early stages. We welcome help from the community for documenting these tools and constructing new ones along the way. We are always happy to rep community-blessed tools if they are better than our own. We welcome anyone to contribute to the Kadena Community projects repository with your own project or add to existing ones. So far, the community projects have yielded both a great terminal wallet with Bag of Holding, and a blazing fast GPU miner courtesy of Alex Khonovalov, Edmund Noble and myriad other insanely smart community members.

Thanks to everyone who contributed, and please feel free to raise your questions to me in Discord — my handle is one of @topos, @pitopos, or @emilypi depending on where I am on the internet. I’m perpetually glued to my screen, so I’ll usually answer if you find me. In the event I’m sleeping, there may be a delay.

Glossary

  • Keyset: Refers to the Pact Keyset authorization scheme. These are a set of public keys in addition to a predicate function (e.g. keys-all, keys-any etc.) that decides the authorization policy for the keys in the keyset. For example, if I have a set of keys with the keys-all predicate, then all keys must be present as signers in a transaction to do anything with the keyset.
We’re also on: Twitter | Linkedin | Github| Reddit| Discord

Kadena

Kadena is powering new ideas and business models with a…

Emily Pillmore

Written by

Engineer @ Kadena, Category + Homotopy Theorist

Kadena

Kadena

Kadena provides a hybrid blockchain platform, featuring the only sharded and scalable layer-1 PoW public network. Kadena solves the scaling challenges of Bitcoin and the security issues of Ethereum.

Emily Pillmore

Written by

Engineer @ Kadena, Category + Homotopy Theorist

Kadena

Kadena

Kadena provides a hybrid blockchain platform, featuring the only sharded and scalable layer-1 PoW public network. Kadena solves the scaling challenges of Bitcoin and the security issues of Ethereum.

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