Skip to main content

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.

NOTE

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 Dual Rewards for your pool, look here 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.

NOTE

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 the submit_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:


_3
let toBase64 = (obj) => {
_3
return Buffer.from(JSON.stringify(obj)).toString("base64");
_3
};

4. Constructing the setup_pools message

NOTE

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.

_17
let 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.

NOTE

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.


_10
let config;
_10
_10
const query = await lcd.wasm.contractQuery(
_10
generatorAddress,
_10
{
_10
"config": {}
_10
}
_10
).then(result => { config = result });
_10
_10
config.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.

NOTE

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
_79
let toBase64 = (obj) => {
_79
return Buffer.from(JSON.stringify(obj)).toString("base64");
_79
};
_79
_79
// config query
_79
_79
let config;
_79
_79
const query = await lcd.wasm.contractQuery(
_79
generatorAddress,
_79
{
_79
"config": {}
_79
}
_79
).then(result => { config = result });
_79
_79
config.active_pools.push("new_lp_token", "new_alloc_points")
_79
_79
// proposal message
_79
_79
let 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
_79
const 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
_79
let fee = new Fee(2000000, { uluna: 100000 });
_79
_79
let tx = await wallet.createAndSignTx({
_79
msgs: [integrateDualRewards],
_79
fee,
_79
chainID: 'phoenix-1',
_79
});
_79
_79
let result = await lcd.tx.broadcast(tx, 'phoenix-1');
_79
_79
console.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!