Implicit Accounts
Background
Implicit accounts work similarly to Bitcoin/Ethereum accounts.
- They allow you to reserve an account ID before it's created by generating a ED25519 key-pair locally.
- This key-pair has a public key that maps to the account ID.
- The account ID is a lowercase hex representation of the public key.
- An ED25519 Public key contains 32 bytes that maps to 64 characters account ID.
- The corresponding secret key allows you to sign transactions on behalf of this account once it's created on chain.
Specifications
Creating an account locally
For a purpose of this demo, we'll use the betanet
network.
Set betanet
network
export NEAR_ENV=betanet
Generating a key-pair first
near generate-key tmp1
Example Output
Generated key pair with ed25519:BGCCDDHfysuuVnaNVtEhhqeT4k9Muyem3Kpgq2U1m9HX public key
It generates a key-pair for tmp1
account ID. The new public key is ed25519:BGCCDDHfysuuVnaNVtEhhqeT4k9Muyem3Kpgq2U1m9HX
.
NEAR's string representation of a public key is <curve>:<data>
.
- Curve is either
ed25519
orsecp256k1
. For implicit accounts we only supported25519
. - Data is a base58 encoding of the public key. For
ed25519
it contains 32 bytes.
This command generated a key-pair locally and stored it locally at:
~/.near-credentials/betanet/tmp1.json
Viewing the key-pair
Run this command to print the content of the key-pair file:
cat ~/.near-credentials/betanet/tmp1.json
Content:
{"account_id":"tmp1","public_key":"ed25519:BGCCDDHfysuuVnaNVtEhhqeT4k9Muyem3Kpgq2U1m9HX","private_key":"ed25519:4qAABW9HfVW4UNQjuQAaAWpB21jqoP58kGqDia18FZDRat6Lg6TLWdAD9FyvAd3PPQLYF4hhx2mZAotJudVjoqfs"}
As you can see, it's a valid json-file and public key matches the one we generated.
The private_key
is a secret/private key of the key pair that can be used to sign transactions with the corresponding public key.
Converting a public key to an account ID.
Let's convert a public key from NEAR string representation ed25519:BGCCDDHfysuuVnaNVtEhhqeT4k9Muyem3Kpgq2U1m9HX
The easiest way is to use near-cli
with interactive console repl
1) Start near repl
:
near repl
2) Store your base58 public key to a local constant:
const pk58 = 'ed25519:BGCCDDHfysuuVnaNVtEhhqeT4k9Muyem3Kpgq2U1m9HX'
3) Now let's parse the public key and convert it to the hex in one line:
nearAPI.utils.PublicKey.fromString(pk58).data.toString('hex')
The output string is the account ID in hex (without '
):
'98793cd91a3f870fb126f66285808c7e094afcfc4eda8a970f6648cdf0dbd6de'
Now the new account ID is 98793cd91a3f870fb126f66285808c7e094afcfc4eda8a970f6648cdf0dbd6de
.
4) We can now give this account ID to someone and ask them to transfer tokens.
Moving the temporary key-pair
Finally, we need to move tmp1.json
key-pair to the real account ID, so that near-cli
can use it to sign transactions.
Let's first export our account ID to a bash env variable:
export ACCOUNT="98793cd91a3f870fb126f66285808c7e094afcfc4eda8a970f6648cdf0dbd6de"
Now we can move the tmp1.json
file:
mv ~/.near-credentials/betanet/tmp1.json ~/.near-credentials/betanet/$ACCOUNT.json
NOTE: While .json
key-pair file still contains the "account_id":"tmp1"
, it's okay. Because near-cli
doesn't care.
Assuming you've received tokens on your new account, you can transfer from it using the following command:
near $ACCOUNT <receiver> <amount>
You can also replace $ACCOUNT
with your actual account ID, e.g.
near send 98793cd91a3f870fb126f66285808c7e094afcfc4eda8a970f6648cdf0dbd6de <receiver> <amount>
Transferring to the implicit account
Let's say someone gives you their account ID 0861ea8ddd696525696ccf3148dd706c4fda981c64d8a597490472594400c223
. You can just transfer to it by running:
near send <your_account_id> 0861ea8ddd696525696ccf3148dd706c4fda981c64d8a597490472594400c223 <amount>
BONUS: Converting public key using python (for learning purposes)
For this flow we'll use python3
(with version 3.5+
) with base58
library.
You can install this library with pip3
:
pip3 install --user base58
Start python3 interpreter:
python3
The first thing is to get the data part from the public key (without ed25519:
prefix). Let's store it in a variable pk58
:
pk58 = 'BGCCDDHfysuuVnaNVtEhhqeT4k9Muyem3Kpgq2U1m9HX'
Now let's import base58:
import base58
Finally, let's convert our base58 public key representation to bytes and then to hex:
base58.b58decode(pk58).hex()
Output:
'98793cd91a3f870fb126f66285808c7e094afcfc4eda8a970f6648cdf0dbd6de'
This gives us the same account ID as near-cli
, so this is encouraging.
Note: The default network for near-cli
is testnet
. If you would like to change this to mainnet
or betanet
, please see near-cli
network selection for instructions.