Add Renec to Your Exchange
This guide describes how to add Renec's native token RENEC to your cryptocurrency exchange.
#
Node SetupWe highly recommend setting up at least two nodes on high-grade computers/cloud instances, upgrading to newer versions promptly, and keeping an eye on service operations with a bundled monitoring tool.
This setup enables you:
- to have a self-administered gateway to the Renec mainnet-beta cluster to get data and submit withdrawal transactions
- to have full control over how much historical block data is retained
- to maintain your service availability even if one node fails
Renec nodes demand relatively high computing power to handle our fast blocks and high TPS. For specific requirements, please see hardware recommendations.
To run an api node:
- Install the Renec command-line tool suite
- Start the validator with at least the following parameters:
Customize --ledger
to your desired ledger storage location, and --rpc-port
to the port you want to expose.
The --entrypoint
and --expected-genesis-hash
parameters are all specific to the cluster you are joining.
Current parameters for Mainnet Beta
The --limit-ledger-size
parameter allows you to specify how many ledger
shreds your node retains on disk. If you do not
include this parameter, the validator will keep the entire ledger until it runs
out of disk space. The default value attempts to keep the ledger disk usage
under 500GB. More or less disk usage may be requested by adding an argument to
--limit-ledger-size
if desired. Check renec-validator --help
for the
default limit value used by --limit-ledger-size
. More information about
selecting a custom limit value is available
here.
Specifying one or more --known-validator
parameters can protect you from booting from a malicious snapshot. More on the value of booting with known validators
Optional parameters to consider:
--private-rpc
prevents your RPC port from being published for use by other nodes--rpc-bind-address
allows you to specify a different IP address to bind the RPC port
Here is an example of validator command for mainnet-beta cluster
#
Ledger ContinuityBy default, each of your nodes will boot from a snapshot provided by one of your
known validators. This snapshot reflects the current state of the chain, but
does not contain the complete historical ledger. If one of your node exits and
boots from a new snapshot, there may be a gap in the ledger on that node. In
order to prevent this issue, add the --no-snapshot-fetch
parameter to your
renec-validator
command to receive historical ledger data instead of a
snapshot.
Do not pass the --no-snapshot-fetch
parameter on your initial boot as it's not
possible to boot the node all the way from the genesis block. Instead boot from
a snapshot first and then add the --no-snapshot-fetch
parameter for reboots.
It is important to note that the amount of historical ledger available to your nodes from the rest of the network is limited at any point in time. Once operational if your validators experience significant downtime they may not be able to catch up to the network and will need to download a new snapshot from a known validator. In doing so your validators will now have a gap in its historical ledger data that cannot be filled.
#
Minimizing Validator Port ExposureThe validator requires that various UDP and TCP ports be open for inbound traffic from all other Renec validators. While this is the most efficient mode of operation, and is strongly recommended, it is possible to restrict the validator to only require inbound traffic from one other Renec validator.
First add the --restricted-repair-only-mode
argument. This will cause the
validator to operate in a restricted mode where it will not receive pushes from
the rest of the validators, and instead will need to continually poll other
validators for blocks. The validator will only transmit UDP packets to other
validators using the Gossip and ServeR ("serve repair") ports, and only
receive UDP packets on its Gossip and Repair ports.
The Gossip port is bi-directional and allows your validator to remain in contact with the rest of the cluster. Your validator transmits on the ServeR to make repair requests to obtaining new blocks from the rest of the network, since Turbine is now disabled. Your validator will then receive repair responses on the Repair port from other validators.
To further restrict the validator to only requesting blocks from one or more
validators, first determine the identity pubkey for that validator and add the
--gossip-pull-validator PUBKEY --repair-validator PUBKEY
arguments for each
PUBKEY. This will cause your validator to be a resource drain on each validator
that you add, so please do this sparingly and only after consulting with the
target validator.
Your validator should now only be communicating with the explicitly listed validators and only on the Gossip, Repair and ServeR ports.
#
Setting up Deposit AccountsRenec accounts do not require any on-chain initialization; once they contain some RENEC, they exist. To set up a deposit account for your exchange, simply generate a Renec keypair using any of our wallet tools.
We recommend using a unique deposit account for each of your users.
Renec accounts must be made rent-exempt by containing 2-years worth of
rent in RENEC. In order to find
the minimum rent-exempt balance for your deposit accounts, query the
getMinimumBalanceForRentExemption
endpoint:
#
Offline AccountsYou may wish to keep the keys for one or more collection accounts offline for greater security. If so, you will need to move RENEC to hot accounts using our offline methods.
#
Listening for DepositsWhen a user wants to deposit RENEC into your exchange, instruct them to send a transfer to the appropriate deposit address.
#
Poll for BlocksTo track all the deposit accounts for your exchange, poll for each confirmed block and inspect for addresses of interest, using the JSON-RPC service of your Renec API node.
- To identify which blocks are available, send a
getBlocks
request, passing the last block you have already processed as the start-slot parameter:
Not every slot produces a block, so there may be gaps in the sequence of integers.
- For each block, request its contents with a
getBlock
request:
The preBalances
and postBalances
fields allow you to track the balance
changes in every account without having to parse the entire transaction. They
list the starting and ending balances of each account in
lamports, indexed to the accountKeys
list. For
example, if the deposit address if interest is
47Sbuv6jL7CViK9F2NMW51aQGhfdpUu7WNvKyH645Rfi
, this transaction represents a
transfer of 218099990000 - 207099990000 = 11000000000 lamports = 11 RENEC
If you need more information about the transaction type or other specifics, you can request the block from RPC in binary format, and parse it using either our Rust SDK or Javascript SDK.
#
Address HistoryYou can also query the transaction history of a specific address. This is generally not a viable method for tracking all your deposit addresses over all slots, but may be useful for examining a few accounts for a specific period of time.
- Send a
getSignaturesForAddress
request to the api node:
- For each signature returned, get the transaction details by sending a
getTransaction
request:
#
Sending WithdrawalsTo accommodate a user's request to withdraw RENEC, you must generate a Renec transfer transaction, and send it to the api node to be forwarded to your cluster.
#
SynchronousSending a synchronous transfer to the Renec cluster allows you to easily ensure that a transfer is successful and finalized by the cluster.
Renec's command-line tool offers a simple command, renec transfer
, to
generate, submit, and confirm transfer transactions. By default, this method
will wait and track progress on stderr until the transaction has been finalized
by the cluster. If the transaction fails, it will report any transaction errors.
The Renec Javascript SDK
offers a similar approach for the JS ecosystem. Use the SystemProgram
to build
a transfer transaction, and submit it using the sendAndConfirmTransaction
method.
#
AsynchronousFor greater flexibility, you can submit withdrawal transfers asynchronously. In these cases, it is your responsibility to verify that the transaction succeeded and was finalized by the cluster.
Note: Each transaction contains a recent blockhash to indicate its liveness. It is critical to wait until this blockhash expires before retrying a withdrawal transfer that does not appear to have been confirmed or finalized by the cluster. Otherwise, you risk a double spend. See more on blockhash expiration below.
First, get a recent blockhash using the getFees
endpoint
or the CLI command:
In the command-line tool, pass the --no-wait
argument to send a transfer
asynchronously, and include your recent blockhash with the --blockhash
argument:
You can also build, sign, and serialize the transaction manually, and fire it off to
the cluster using the JSON-RPC sendTransaction
endpoint.
#
Transaction Confirmations & FinalityGet the status of a batch of transactions using the
getSignatureStatuses
JSON-RPC endpoint.
The confirmations
field reports how many
confirmed blocks have elapsed since the
transaction was processed. If confirmations: null
, it is finalized.
#
Blockhash ExpirationYou can check whether a particular blockhash is still valid by sending a
getFeeCalculatorForBlockhash
request with the blockhash as a parameter. If the response value is null
, the
blockhash is expired, and the withdrawal transaction using that blockhash should
never succeed.
#
Validating User-supplied Account Addresses for WithdrawalsAs withdrawals are irreversible, it may be a good practice to validate a user-supplied account address before authorizing a withdrawal in order to prevent accidental loss of user funds.
#
Basic verficationRenec addresses a 32-byte array, encoded with the bitcoin base58 alphabet. This results in an ASCII text string matching the following regular expression:
This check is insufficient on its own as Renec addresses are not checksummed, so typos cannot be detected. To further validate the user's input, the string can be decoded and the resulting byte array's length confirmed to be 32. However, there are some addresses that can decode to 32 bytes despite a typo such as a single missing character, reversed characters and ignored case
#
Advanced verificationDue to the vulnerability to typos described above, it is recommended that the balance be queried for candidate withdraw addresses and the user prompted to confirm their intentions if a non-zero balance is discovered.
#
Valid ed25519 pubkey checkThe address of a normal account in Renec is a Base58-encoded string of a 256-bit ed25519 public key. Not all bit patterns are valid public keys for the ed25519 curve, so it is possible to ensure user-supplied account addresses are at least correct ed25519 public keys.
#
JavaHere is a Java example of validating a user-supplied address as a valid ed25519 public key:
The following code sample assumes you're using the Maven.
pom.xml
:
#
Minimum Deposit & Withdrawal AmountsEvery deposit and withdrawal of RENEC must be greater or equal to the minimum rent-exempt balance for the account at the wallet address (a basic RENEC account holding no data), currently: 0.000890880 RENEC
Similarly, every deposit account must contain at least this balance.
#
Supporting the RPL Token StandardRPL Token is the standard for wrapped/synthetic token creation and exchange on the Renec blockchain.
The RPL Token workflow is similar to that of native RENEC tokens, but there are a few differences which will be discussed in this section.
#
Token MintsEach type of RPL Token is declared by creating a mint account. This account stores metadata describing token features like the supply, number of decimals, and various authorities with control over the mint. Each RPL Token account references its associated mint and may only interact with RPL Tokens of that type.
rpl-token
CLI Tool#
Installing the RPL Token accounts are queried and modified using the rpl-token
command line
utility. The examples provided in this section depend upon having it installed
on the local system.
rpl-token
is distributed from Rust crates.io
via the Rust cargo
command line utility. The latest version of cargo
can be
installed using a handy one-liner for your platform at rustup.rs.
Once cargo
is installed, rpl-token
can be obtained with the following command:
You can then check the installed version to verify
Which should result in something like
#
Account CreationRPL Token accounts carry additional requirements that native System Program accounts do not:
- RPL Token accounts must be created before an amount of tokens can be
deposited. Token accounts can be created explicitly with the
rpl-token create-account
command, or implicitly by therpl-token transfer --fund-recipient ...
command. - RPL Token accounts must remain rent-exempt for the duration of their existence and therefore require a small amount of native RENEC tokens be deposited at account creation. For RPL Token v2 accounts, this amount is 0.00203928 RENEC (2,039,280 lamports).
#
Command LineTo create an RPL Token account with the following properties:
- Associated with the given mint
- Owned by the funding account's keypair
#
ExampleOr to create an RPL Token account with a specific keypair:
#
Checking an Account's Balance#
Command Line#
Example#
Token TransfersThe source account for a transfer is the actual token account that contains the amount.
The recipient address however can be a normal wallet account. If an associated
token account for the given mint does not yet exist for that wallet, the
transfer will create it provided that the --fund-recipient
argument as
provided.
#
Command Line#
Example#
DepositingSince each (wallet, mint)
pair requires a separate account on chain. It is
recommended that the addresses for these accounts be derived from RENEC deposit
wallets using the
Associated Token Account (ATA)
scheme and that only deposits from ATA addresses be accepted.
Monitoring for deposit transactions should follow the block polling
method described above. Each new block should be scanned for successful
transactions referencing user token-account derived addresses. The
preTokenBalance
and postTokenBalance
fields from the transaction's metadata
must then be used to determine the effective balance change. These fields will
identify the token mint and account owner (main wallet address) of the affected
account.
Note that if a receiving account is created during the transaction, it will have no
preTokenBalance
entry as there is no existing account state. In this
case, the initial balance can be assumed to be zero.
#
WithdrawingThe withdrawal address a user provides must be the that of their RENEC wallet.
Before executing a withdrawal transfer, the exchange should check the address as described above. Additionally this address must be owned by the System Program and have no account data. If the address has no RENEC balance, user confirmation should be obtained before proceeding with the withdrawal. All other withdrawal addresses must be rejected.
From the withdrawal address, the Associated Token Account (ATA) for the correct mint is derived and the transfer issued to that account via a TransferChecked instruction. Note that it is possible that the ATA address does not yet exist, at which point the exchange should fund the account on behalf of the user. For RPL Token v2 accounts, funding the withdrawal account will require 0.00203928 RENEC (2,039,280 lamports).
Template rpl-token transfer
command for a withdrawal:
#
Other Considerations#
Freeze AuthorityFor regulatory compliance reasons, an RPL Token issuing entity may optionally choose to hold "Freeze Authority" over all accounts created in association with its mint. This allows them to freeze the assets in a given account at will, rendering the account unusable until thawed. If this feature is in use, the freeze authority's pubkey will be registered in the RPL Token's mint account.
#
Testing the IntegrationBe sure to test your complete workflow on Renec devnet and testnet
clusters before moving to production on mainnet-beta. Devnet
is the most open and flexible, and ideal for initial development, while testnet
offers more realistic cluster configuration. Both devnet and testnet support a faucet,
run renec airdrop 1
to obtain some devnet or testnet RENEC for developement and testing.