Request Astro Emissions
ASTRO is the native token of Astroport, forming an essential part of its rewards system. It works to amplify the incentives for liquidity providers, encouraging a diverse and robust ecosystem. To request ASTRO emissions for a pool, you will need to submit a governance proposal to the Astral Assembly and obtain approval to move forward.
This section is specifically designed for developers who wish to request ASTRO emissions for a pool, without concerning themselves with third-party token emissions. If you're interested in other rewards for your pool, look at Deploying Incentives instead.
In the following sections, we will guide you through the steps of crafting and submitting a governance proposals for Astro Emissions.Sections 1-3 dive into the heart of the governance proposal process. Sections 4-5 will guide you through crafting a proposal message dedicated to requesting ASTRO emissions. The final section will bring it all together, focusing on the formulation and submission of the combined proposal message.
Astroport's governance hub is currently hosted on Terra. As such, for deployments on other blockchains (Neutron, Injective, and Sei), you will need to submit your governance proposal to the Assembly contract on Terra. Upon approval, this proposal will trigger a cross-chain governance operation, which executes the approved proposal on the specific blockchain to which the message was addressed.
Steps
1. Construct send
message
To initiate the submission of a proposal, a contract call needs to be executed that calls the send
endpoint within the xASTRO token contract. The send
operation requires three parameters:
contract
: This refers to the address where xASTRO tokens are being dispatched. In this context, it should be the Assembly address.amount
: This specifies the quantity of xASTRO tokens to be sent or staked. For mainnet, it's currently 30,000 xASTRO (1000 xASTRO for testnet).msg
: This is a binary-encoded message that contains a contract call to thesubmit_proposal
endpoint. This message will be discussed below.
_17{_17 "send": {_17 "contract": assemblyAddress, _17 "amount": "30000", _17 "msg": toBase64(_17 {_17 "submit_proposal": {_17 "title": "Integrate ASTRO emissions", _17 "description": "Proposal to integrate ASTRO emissisons", _17 "link": "https://forum.astroport.fi/", _17 "messages": [setup_pools], _17 "ibc_channel": "..."_17 }_17 }_17 ) _17 }_17}
2. Construct submit_proposal
message
The msg
parameter in Step 1 requires a binary-encoded message, which essentially includes a contract call to the submit_proposal
endpoint within the Assembly contract. You will need to structure your submit_proposal
message with the following parameters:
title
: This is the title of your proposal.description
: This provides a more detailed explanation of your proposal.link
: This should be the URL to the forum discussion for your proposal.messages
: This field includes your proposal messages for requesting ASTRO emissions. This message outline the changes to be made if your proposal is approved. The specific structure and content of these messages will be discussed in subsequent steps.ibc_channel
: This field is reserved for proposals that should be executed on a different chain. If your proposal is meant to be executed cross-chain, specify the governance channel for the target chain.
_17{_17 "send": {_17 "contract": assemblyAddress, _17 "amount": "30000", _17 "msg": toBase64(_17 {_17 "submit_proposal": {_17 "title": "Integrate ASTRO emissions", _17 "description": "Proposal to integrate ASTRO emissisons", _17 "link": "https://forum.astroport.fi/", _17 "messages": [setup_pools], _17 "ibc_channel": "..."_17 }_17 }_17 ) _17 }_17}
3. Define an encoding function
Next, you'll need to encode the submit_proposal
message you've constructed. As previously outlined in Step 1, the msg
parameter requires a binary-encoded string. In Step 2, we prepped our submit_proposal
message for encoding using a toBase64
function. Now it's time to actually perform that encoding.
Please note that the toBase64
function must be defined in your code environment to use it for encoding purposes. This function is crucial to convert the JSON string representation of our message into a base64 encoded string.
Here's an example of how to define the toBase64
function in JavaScript:
_3let toBase64 = (obj) => {_3 return Buffer.from(JSON.stringify(obj)).toString("base64");_3};
4. Constructing the setup_pools
message
In the scenario where you're executing a proposal via a script, it's advisable to compartmentalize each proposal message into distinct variables. These variables then get placed into the message vector of our proposal. This approach enhances the code modularity and maintainability.
setup_pools
is our first proposal message. It calls the setup_pools
endpoint in the Generator contract and expects a parameter named pools
. This parameter contains a vector of LP token addresses and their corresponding allocation points, which is also stored in a binary-encoded format using the toBase64 function we defined earlier.
It's crucial to avoid two common mistakes while working with the setup_pools
function:
- The function expects LP token addresses, not pair addresses.
- The function expects a vector of LP token addresses. If a single address is specified, it overwrites all active pools with the new list. Therefore, you should query the generator contract to incorporate previous LP token addresses and allocation points. This step will be discussed next.
_17let setup_pools = {_17 {_17 "wasm": {_17 "execute": {_17 "contract_addr": generatorAddress, _17 "msg": toBase64(_17 {_17 "setup_pools": {_17 "pools": config.active_pools_17 }_17 }_17 ),_17 "funds": []_17 }_17 }_17 }_17}
5. Query config.active_pools
The previous step presented the setup_pools
proposal message, calling the setup_pools
endpoint in the Generator contract. This message carries an array of liquidity pool tokens and their associated allocation points.
When you specify a single liquidity pool token address in the setup_pools message, it replaces all active pools with the one specified in the message. To preserve existing pools while introducing new ones, you need to query the Generator contract to fetch the currently active pool addresses and their allocation points.
The code snippet below demonstrates this process. It begins by querying the Generator contract to obtain its current configuration. It then appends a new liquidity pool token address and allocation points to the active_pools
list. This updated list will then be utilized in our setup_pools
proposal message.
In cases where the community desires to reduce allocation points for specific pools, proposal submitters may need to modify the config.active_pools
list accordingly.
_10let config;_10_10const query = await lcd.wasm.contractQuery(_10 generatorAddress, _10 {_10 "config": {}_10 }_10).then(result => { config = result });_10_10config.active_pools.push("new_lp_token", "new_alloc_points")
6. Complete proposal
This section brings all the individual pieces together to form our complete proposal submission. This involves organizing our proposal messages and executing the final submit_proposal
call.
This example does not include the initial Terra LCD setup. To learn more, visit the feather.js docs.
Additionally, make sure to adjust all placeholders (e.g., generatorAddress
, new_lp_token
, new_alloc_points
) to your specific use case.
_79_79// terra lcd setup ... _79_79// encoder function_79_79let toBase64 = (obj) => {_79 return Buffer.from(JSON.stringify(obj)).toString("base64");_79};_79_79// config query_79_79let config;_79_79const query = await lcd.wasm.contractQuery(_79 generatorAddress, _79 {_79 "config": {}_79 }_79).then(result => { config = result });_79_79config.active_pools.push("new_lp_token", "new_alloc_points")_79_79// proposal message_79_79let setup_pools = {_79 {_79 "wasm": {_79 "execute": {_79 "contract_addr": generatorAddress, _79 "msg": toBase64(_79 {_79 "setup_pools": {_79 "pools": config.active_pools_79 }_79 }_79 ),_79 "funds": []_79 }_79 }_79 }_79}_79_79// send tx_79_79const integrateDualRewards = new MsgExecuteContract(_79 wallet.key.accAddress('terra'), _79 xastroAddress, _79 {_79 "send": {_79 "contract": assemblyAddress, _79 "amount": "30000", _79 "msg": toBase64(_79 {_79 "submit_proposal": {_79 "title": "Integrate ASTRO emissions", _79 "description": "Proposal to integrate ASTRO emissions", _79 "link": "https://forum.astroport.fi/", _79 "messages": [setup_pools], _79 "ibc_channel": "..."_79 }_79 }_79 ) _79 }_79 }_79)_79_79// broadcast tx_79_79let fee = new Fee(2000000, { uluna: 100000 });_79_79let tx = await wallet.createAndSignTx({_79 msgs: [integrateDualRewards],_79 fee,_79 chainID: 'phoenix-1',_79});_79_79let result = await lcd.tx.broadcast(tx, 'phoenix-1');_79_79console.log(result);
After finalizing your code, you're ready to submit your proposal and play a significant part in the decision-making process of Astroport!