Welcome to py-near’s documentation!

Quick start

At first you have to import all necessary modules

from pynear.account import Account

Then you have to initialize Account

ACCOUNT_ID = "bob.near"
PRIVATE_KEY = "ed25519:..."

acc = Account(ACCOUNT_ID, PRIVATE_KEY)

Next step: check account balance

import asyncio
from pynear.dapps.core import NEAR

async def main():
    await acc.startup()
    print(await acc.get_balance() / NEAR)
    print(await acc.get_balance("bob.near") / NEAR)

asyncio.run(main())

Next step: send 2 NEAR to bob.near

tr = await acc.send_money("bob.near", NEAR * 2)
print(tr.transaction.hash)
print(tr.logs)

Next step: send 2 NEAR to bob.near no waiting for transaction confirmation

transaction_hash = await acc.send_money("bob.near", NEAR * 2, nowait=True)
print(transaction_hash)

Next step: send 0.1 NEAR by phone number

tr = await acc.phone.send_near_to_phone("+15626200110", NEAR // 10)
print(tr.transaction.hash)

Summary

from pynear.account import Account
import asyncio
from pynear.dapps.core import NEAR

ACCOUNT_ID = "bob.near"
PRIVATE_KEY = "ed25519:..."

async def main():
    acc = Account(ACCOUNT_ID, PRIVATE_KEY)

    await acc.startup()
    print(await acc.get_balance() / NEAR)
    print(await acc.get_balance("bob.near") / NEAR)

    tr = await acc.send_money("bob.near", NEAR * 2)
    print(tr.transaction.hash)
    print(tr.logs)

    tr = await acc.phone.send_near_to_phone("+15626200911", NEAR // 10)
    print(tr.transaction.hash)

asyncio.run(main())

Parallel requests

Only one parallel request can be made from one private key. All transaction calls execute sequentially. To make several parallel calls you need to use several private keys

Add 2 new full access keys:

acc = Account("bob.near", private_key1)

for i in range(2):
    signer = InMemorySigner.from_random(AccountId("bob.near"), KeyType.ED25519)
    await acc.add_full_access_public_key(str(signer.public_key))
    print(signer.secret_key)

Now we can call transactions in parallel

acc = Account("bob.near", [private_key1, private_key2, private_key3])
# request time = count transactions / count public keys
tasks = [
    asyncio.create_task(acc.send_money("alisa.near", 1)),
    asyncio.create_task(acc.send_money("alisa.near", 1)),
    asyncio.create_task(acc.send_money("alisa.near", 1)),
]
for t in task:
    await t

Account

Quick start

from pynear.account import Account
import asyncio
from pynear.dapps.core import NEAR

ACCOUNT_ID = "bob.near"
PRIVATE_KEY = "ed25519:..."

async def main():
    acc = Account(ACCOUNT_ID, PRIVATE_KEY)

    await acc.startup()
    print(await acc.get_balance() / NEAR)
    print(await acc.get_balance("bob.near") / NEAR)

    transaction = await acc.send_money("bob.near", NEAR * 2)
    print(tr.transaction.hash)
    print(tr.logs)

    transaction = await acc.phone.send_near_to_phone("+15626200911", NEAR // 10)
    print(tr.transaction.hash)

asyncio.run(main())

Documentation

class Account

This class implement all blockchain functions for your account. Only one parallel request can be made from one private key. All transaction calls execute sequentially.

acc = Account("bob.near", private_key1)

# requests time ~18s
tasks = [
    asyncio.create_task(acc.send_money("alisa.near", 1)),
    asyncio.create_task(acc.send_money("alisa.near", 1)),
    asyncio.create_task(acc.send_money("alisa.near", 1)),
]
for t in task:
    await t

Account() support multikeys. In this case you can make a few parallel requests.

acc = Account("bob.near", [private_key1, private_key2, private_key3])

# requests time ~6s
tasks = [
    asyncio.create_task(acc.send_money("alisa.near", 1)),
    asyncio.create_task(acc.send_money("alisa.near", 1)),
    asyncio.create_task(acc.send_money("alisa.near", 1)),
]
for t in task:
    await t
get_access_key()

Get access key for current account

Returns:

AccountAccessKey

await acc.get_access_key()
get_access_key_list(account_id=None)

Send fungible token to phone number. Reciver will get sms with link to claim tokens. Get access key list for account_id, if account_id is None, get access key list for current account

Parameters:

account_id – if account_id is None, return balance of current account

Returns:

list of PublicKey

keys = await acc.get_access_key_list()
print(len(keys))
fetch_state(phone)

Fetch state for given account

Returns:

state dict

state = await acc.fetch_state()
print(state)
send_money(account_id: str, amount: int, nowait=False)

Send money to account_id

Parameters:
  • account_id – receiver account id

  • amount – amount in yoctoNEAR

  • nowait – if nowait is True, return transaction hash, else wait execution

Returns:

transaction hash or TransactionResult

await acc.send_money('bob.near', NEAR * 3)
view_function(contract_id: str, method_name: str, args: dict)

Call view function on smart contract. View function is read only function, it can’t change state

Parameters:
  • contract_id – smart contract account id

  • method_name – method name to call

  • args – json args to call method

Returns:

result of view function call

result = await acc.view_function("usn.near", "ft_balance_of", {"account_id": "bob.near"})
print(result)
function_call(contract_id: str, method_name: str, args: dict, gas=DEFAULT_ATTACHED_GAS, amount=0, nowait=False)

Call function on smart contract

Parameters:
  • contract_id – smart contract adress

  • method_name – call method name

  • args – json params for method

  • gas – amount of attachment gas

  • amount – amount of attachment NEAR

  • nowait – if nowait is True, return transaction hash, else wait execution

Returns:

transaction hash or TransactionResult

await acc.function_call('usn.near', "ft_transfer", {"receiver_id": "bob.near", "amount": "1000000000000000000000000"})
create_account(account_id: str, public_key: Union[str, bytes], initial_balance: int, nowait=False)
Create new account in subdomian of current account. For example, if current account is “test.near”,

you can create “wwww.test.near”

Parameters:
  • account_id – new account id

  • public_key – add public key to new account

  • initial_balance – amount to transfer NEAR to new account

  • nowait – is nowait is True, return transaction hash, else wait execution

Returns:

transaction hash or TransactionResult

await acc.create_account('test.bob.near', "5X9WvUbRV3aSd9Py1LK7HAndqoktZtcgYdRjMt86SxMj", NEAR * 3)
add_public_key(public_key: Union[str, bytes], receiver_id: str, method_names: List[str] = None, allowance: int = 25000000000000000000000, nowait=False)

Add public key to account with access to smart contract methods

Parameters:
  • public_key – public_key to add

  • receiver_id – smart contract account id

  • method_names – list of method names to allow

  • allowance – maximum amount of gas to use for this key

  • nowait – if nowait is True, return transaction hash, else wait execution

Returns:

transaction hash or TransactionResult

await acc.add_public_key("5X9WvUbRV3aSd9Py1LK7HAndqoktZtcgYdRjMt86SxMj", "usn.near", [])
add_full_access_public_key(public_key: Union[str, bytes], nowait=False)

Add public key to account with full access

Parameters:
  • public_key – public_key to add

  • nowait – if nowait is True, return transaction hash, else wait execution

Returns:

transaction hash or TransactionResult

await acc.add_full_access_public_key("5X9WvUbRV3aSd9Py1LK7HAndqoktZtcgYdRjMt86SxMj")
delete_public_key(public_key: Union[str, bytes], nowait=False)

Delete public key from account

Parameters:
  • public_key – public_key to delete

  • nowait – is nowait is True, return transaction hash, else wait execution

Returns:

transaction hash or TransactionResult

await acc.delete_public_key("5X9WvUbRV3aSd9Py1LK7HAndqoktZtcgYdRjMt86SxMj")
deploy_contract(contract_code: bytes, nowait=False)

Deploy smart contract to account

Parameters:
  • contract_code – smart contract code

  • nowait – if nowait is True, return transaction hash, else wait execution

Returns:

transaction hash or TransactionResult

with open("contract.wasm", "rb") as f:
    contract_code = f.read()
await acc.deploy_contract(contract_code, nowait=True)
stake(contract_code: bytes, nowait=False)

Stake NEAR on account. Account must have enough balance to be in validators pool

Parameters:
  • public_key – public_key to stake

  • amount – amount of NEAR to stake

  • nowait – if nowait is True, return transaction hash, else wait execution

Returns:

transaction hash or TransactionResult

get_balance(account_id: str = None)

Get account balance

Parameters:

account_id – if account_id is None, return balance of current account

Returns:

balance of account in yoctoNEAR

result = await acc.get_balance("usn.near")
print(result)
property phone

Get client for phone.herewallet.near

Returns:

Phone(self)

property ft

Get client for fungible tokens

Returns:

FT(self)

Phone number transfer

Note

Phone number transfer available only for mainnet

Quick start

from pynear.account import Account
from pynear.dapps.fts import FTS
import asyncio

ACCOUNT_ID = "bob.near"
PRIVATE_KEY = "ed25519:..."


async def main():
    acc = Account(ACCOUNT_ID, PRIVATE_KEY)
    await acc.startup()
    transaction = await acc.phone.send_ft_to_phone(FTS.USDC, "+15626200911", 1)
    print(tr.transaction.hash)

asyncio.run(main())

Documentation

class Phone(DappClient)

Client to phone.herewallet.near contract With this contract you can send NEAR and fungible tokens to phone number. Reciver will get notification with link to claim tokens.

acc = Account(...)
phone = acc.phone
await acc.phone.send_near_to_phone("+1234567890", NEAR * 2, "Happy birthday!")
send_near_to_phone(phone: str, amount: float, comment: str = '', nowait: bool = False)

Send NEAR to phone number. Reciver will get sms with link to claim tokens.

Parameters:
  • phone – +X format phone number

  • amount – number of NEAR which will be sent

  • comment – any comment

  • nowait – if nowait is True, return transaction hash, else wait execution

Returns:

transaction hash or TransactionResult

await acc.phone.send_near_to_phone('+79999999999', NEAR * 2*)
send_ft_to_phone(ft: FtModel, phone: str, amount: float, comment: str = '', nowait: bool = False)

Send fungible token to phone number. Reciver will get sms with link to claim tokens.

Parameters:
  • ft – Fungible token model

  • phone – +X format phone number

  • amount – number of FT which will be sent

  • comment

  • nowait – if nowait is True, return transaction hash, else wait execution

Returns:

transaction hash or TransactionResult

# Send 1 USDC to phone number
await acc.phone.send_ft_to_phone(FTS.USDC, '+79999999999', 1)
get_ft_transfers(phone)

Get list of fungible token transfers to phone number :param phone: phone number :return: list of FtTrustTransaction

await acc.phone.get_ft_transfers('+79999999999')
get_near_transfers(phone)

Get list of NEAR transfers to phone number

Parameters:

phone – phone number

Returns:

list of NEAR transfers

await acc.phone.get_near_transfers('+79999999999')
cancel_near_transaction(phone: str, index: int)

Cancel NEAR transfer to phone number. Use index from get_near_transfers() method

Parameters:
  • phone – phone number

  • index – index in transaction list

Returns:

await acc.phone.cancel_near_transaction('+79999999999', 0)
cancel_ft_transaction(phone: str, index: int)

Cancel NEAR transfer to phone number. Use index from get_near_transfers() method

Cancel fungible token transfer to phone number. Use index from get_ft_transfers() method

Parameters:
  • phone – phone number

  • index – index in transaction list

Returns:

await acc.phone.cancel_ft_transaction('+79999999999', 0)

Fungible tokens

Quick start

from pynear.account import Account
from pynear.dapps.fts import FTS
import asyncio

ACCOUNT_ID = "bob.near"
PRIVATE_KEY = "ed25519:..."


async def main():
    acc = Account(ACCOUNT_ID, PRIVATE_KEY)
    await acc.startup()
    # send 5 USDC to azbang.near
    tr = await acc.ft.transfer(FTS.USDC, "azbang.near", 5, force_register=True)
    print(tr.transaction.hash)

asyncio.run(main())

Documentation

class FT(DappClient)

Client to any NEP-141 contract` With this contract you can send fungible tokens to any user

acc = Account(...)
ft = acc.ft
await acc.ft.transfer(FTS.USDC, "azbang.near", 5, force_register=True)
get_ft_balance(ft: FtModel, account_id: str)

Get fungible token balance

Parameters:
  • ft – fungible token model FT.USDC

  • account_id – account id

Returns:

amount // 10**ft.decimal

await acc.ft.get_ft_balance(FTS.USDC, account_id="azbang.near")
get_metadata(ft: FtModel, account_id: str)

Get fungible token metadata

Parameters:

ft – fungible token model FT.USDC

Returns:

FtTokenMetadata

await acc.ft.get_metadata(FTS.USDC)
transfer(ft: FtModel, account_id: str, amount: float, memo: str = '', force_register: bool = False)

Transfer fungible token to account

Parameters:
  • ft – fungible token model FT.USDC

  • receiver_id – receiver account id

  • amount – float amount to transfer. 1 for 1 USDC

  • memo – comment

  • force_register – use storage_deposit() if account is not registered

  • nowait – if nowait is True, return transaction hash, else wait execution

Returns:

transaction hash or TransactionResult

await acc.ft.transfer(FTS.USDC, "azbang.near", 5, force_register=True)
transfer_call(ft: FtModel, account_id: str, amount: float, memo: str = '', force_register: bool = False, nowait: bool = False)

Transfer fungible token to account and call ft_on_transfer() method in receiver contract

Parameters:
  • ft – fungible token model FT.USDC

  • receiver_id – receiver account id

  • amount – float amount to transfer. 1 for 1 USDC

  • memo – comment

  • force_register – use storage_deposit() if account is not registered

  • nowait – if nowait is True, return transaction hash, else wait execution

Returns:

transaction hash or TransactionResult

await acc.ft.transfer_call(FTS.USDC, "azbang.near", 5, force_register=True)
storage_balance_of(ft: FtModel, account_id: str)

Get storage balance of account. The balance must be greater than 0.01 NEAR for some smart contracts in order for the recipient to accept the token

Parameters:
  • contract_id – fungible token contract_id

  • account_id – account id

Returns:

int balance in yoctoNEAR, 1_000_000_000_000_000_000_000_000 for 1 NEAR

await acc.ft.storage_balance_of(FTS.USDC, "azbang.near")
storage_deposit(ft: FtModel, account_id: str, amount: int = NEAR // 50)

Deposit storage balance for account. The balance must be greater than 0.01 NEAR for some smart contracts

Parameters:
  • ft – fungible token model FT.USDC

  • account_id – receiver account id

  • amount – in amount of yoctoNEAR

Returns:

await acc.ft.storage_deposit(FTS.USDC, "azbang.near")

Staking

Note

Class to stake NEAR on liquid staking. You can stake NEAR and withdraw at any time without fees

Read more about staking: https://docs.herewallet.app/technology-description/readme

Quick start

from pynear.account import Account
from pynear.dapps.fts import FTS
import asyncio

ACCOUNT_ID = "bob.near"
PRIVATE_KEY = "ed25519:..."


async def main():
    acc = Account(ACCOUNT_ID, PRIVATE_KEY)
    await acc.startup()
    transaction = await acc.staking.stake(10000)
    print(tr.transaction.hash)

    transaction = await acc.staking.receive_dividends()
    print(tr.logs)

    transaction = await acc.staking.unstake(10000)
    print(tr.transaction.hash)

asyncio.run(main())

Documentation

class Staking(DappClient)

Client to storage.herewallet.near contract With this contract you can stake NEAR without blocking and receive passive income ~9% APY

acc = Account(...)
staking = acc.staking
class StakingData(DappClient)
apy_value: int

current APY value * 100 (908=9.08%)

last_accrual_ts: int

Last UTC timestamp of accrued recalc

accrued: int

Total accrued in yoctoNEAR, which can be receiver by receive_dividends() call

transfer(account_id: str, amount: int, memo: str = '', force_register: bool = False)

Transfer hNEAR to account

Parameters:
  • receiver_id – receiver account id

  • amount – amount in yoctoNEAR

  • memo – comment

:param nowait if True, method will return before transaction is confirmed :return: transaction hash ot TransactionResult

await acc.staking.transfer("azbang.near", 10000)
transfer_call(account_id: str, amount: int, memo: str = '', force_register: bool = False)

Transfer hNEAR to account and call on_transfer_call() on receiver smart contract

Parameters:
  • receiver_id – receiver account id

  • amount – amount in yoctoNEAR

  • memo – comment

:param nowait if True, method will return before transaction is confirmed :return: transaction hash ot TransactionResult

await acc.staking.transfer_call("azbang.near", 10000)
get_staking_amount(account_id: str)

Get staking balance of account.

Parameters:

account_id – account id

:param nowait if True, method will return before transaction is confirmed :return: int balance in yoctoNEAR

amount = await acc.staking.get_staking_amount("azbang.near")
print(amount)
get_user(account_id: str)

Get user staking parameters

Parameters:

account_id – account id

Returns:

StakingData

data = await acc.staking.get_user("azbang.near")
print(data.apy_value / 100)
stake(amount: int, nowait: bool = False)

Deposit staking for account

Parameters:
  • amount – in amount of yoctoNEAR

  • nowait – if True, method will return before transaction is confirmed

Returns:

transaction hash or TransactionResult

res = await acc.staking.stake(1_000_000_000_000_000)
print(res.transaction.hash)
unstake(amount: int, nowait: bool = False)

Withdraw from staking

Parameters:
  • amount – in amount of yoctoNEAR

  • nowait – if True, method will return before transaction is confirmed

Returns:

transaction hash or TransactionResult

res = await acc.staking.unstake(1_000_000_000_000_000)
print(res.transaction.hash)
receive_dividends(nowait: bool = False)

Receive dividends. user.accrued yoctoNEAR amount will transfer to staking balance

Parameters:

nowait – if True, method will return before transaction is confirmed

Returns:

transaction hash ot TransactionResult

res = await acc.staking.receive_dividends()
print(res.transaction.hash)

Delegate Transactions

Description

NEAR Protocol supports delegate transactions since version 0.17.0 This is a special type of transaction which can be created and signed by one account but sent on behalf of another account. Delegate transactions used to pay for gas for a third party.

These transactions are performed in three steps.

  1. Alice creates a delegate_action and specifies all the actions, public key and recipient.

  2. Alice signs delegate_action with her private key and gives it to Bob.

  3. Bob forms a normal transaction from one action - delegate_action, signs it and sends to the blockchain. In fact, the Alice transaction is executed, but the Bob pays for the gas.

Make delegate transaction with py_near

The following Python function creates and signs a delegate transaction.

  1. Create a DelegateActionModel object with the create_delegate_action method. This method takes the following parameters:

    • actions: A list of Action objects. In this example, we use a TransferAction object.

    • receiver_id: The NEAR Protocol account ID where you want to send the transaction.

  2. Sign the delegate transaction with the sign_delegate_transaction method. This method takes the following parameters:

    • delegate_action: The DelegateActionModel object you created in the previous step.

    • private_key: The private key of the NEAR Protocol account that you want to use to sign the transaction.

  3. Execute the delegate transaction with the call_delegate_transaction method. This method takes the following parameters:

    • delegate_action: The DelegateActionModel object you created in the previous step.

    • signature: The signature of the delegate transaction that you created in the previous step.

You can execute this transaction from any NEAR Protocol account.

from py_near.account import Account
from py_near_primitives import TransferAction
import ed25519


async def f():
    account = Account(
        "alisa.near",
        "ed25519::...",
        "https://nrpc.herewallet.app",
    )

    action = await account.create_delegate_action(actions=[TransferAction(1)], receiver_id="illia.near")
    sign = account.sign_delegate_transaction(action)

    account_to_execute = Account(
        "bob.near",
        "ed25519:...",
        "https://nrpc.herewallet.app",
    )
    res = account_to_execute acc.call_delegate_transaction(
        delegate_action=action,
        signature=sign,
    )

In this example, we transfer 1 yNEAR from alisa.near to illia.near and pay for gas from bob.near balance.

Note

Replace the ed25519 public and private keys in the Account objects with your actual account keys.

You also need to replace the receiver_id value in the create_delegate_action method with the actual NEAR Protocol account ID where you want to send the transaction.

Warning

For now not all rpc support delegate transactions. You can use https://nrpc.herewallet.app for testing.

Make delegate transaction manually

The following Python function creates and signs a delegate transaction from alisa.near account.

from py_near.account import Account
from py_near_primitives import TransferAction
from py_near.models import DelegateActionModel
import ed25519

private_key = ed25519.SigningKey(base58.b58decode("...."))
public_key = base58.b58encode(private_key.get_verifying_key().to_bytes()).decode()

action = DelegateActionModel(
    sender_id="alisa.near",
    receiver_id="illia.near",
    actions=[TransferAction(1)],
    nonce=ALISA_KEY_NONCE + 1,
    max_block_height=CURRENT_BLOCK_HEIGHT + 1,
    public_key=public_key,
)

sign = private_key.sign(action.nep461_hash)

And now send this transaction and pay for gas from bob.near balance.

from py_near.account import Account

account_to_execute = Account(
        "bob.near",
        "ed25519:...",
        "https://nrpc.herewallet.app",
    )
account_to_execute = await acc.call_delegate_transaction(
    delegate_action=action,
    signature=sign,
)