Nexera-Fi SDKUsage Examples

Executing Actions via Microservices

executeInMicroservice Function

The executeInMicroservice function facilitates the execution of a set of actions through an Orchestrator instance in a single on-chain transaction, with transaction delegation to an external microservice.

Internally, the function prepares the appropriate transaction request object based on the input parameters (orchestratorAddress, actions, and gasLimit) and then dispatches it to the specified external microservice via a POST request. The microservice, acting as a transaction relayer, manages a designated wallet which sends the transaction object on the blockchain to be resolved.

async function executeInMicroservice(
  orchestratorAddress: string,
  actions: Action[],
  failedCaseTx: number,
  microserviceUrl: string,
  gasLimit: number,
  network: ChainId
);

Parameters

NameTypeDescription
orchestratorAddressstringThe address of the Orchestrator instance
actionsAction[]An array of actions to be executed by the Orchestrator.

Each action specifies the Adapter, operation, token compositions, and any additional data required by the respective Adapter
failedCaseTxnumberNumber of attempts if the transaction fails
microserviceUrlstringThe URL of the external microservice
gasLimitnumberThe gas limit for the transaction
networkChainIdThe chain ID of the target blockchain network

Action Type

The Action type encapsulates the information required for executing a specific action. It includes the following:

  • The address of the Adapter to be employed
  • The operation code
  • The token compositions to be sent to the Adapter
  • The minimum expected token compositions to be received
  • Any additional ABI encoded data specific to the Adapter's operation
type Action = {
    adapter: string,
    op: number,
    send: TokenAmount[],
    minReceive: TokenAmount[],
    extraData: string
}

TokenAmount Type

This type represents a combination of a token address and a corresponding amount. It is used to define the token compositions involved in each action.

type TokenAmount = {
    token: string,
    amount: BigNumber
}

Example

The following example demonstrates how to use the executeInMicroservice function to efficiently execute a set of actions on an Orchestrator through an external microservice.

Specifically, the set of actions in this example is the following:

  • Depositing DAI and WETH in Uniswap V3 (first action)
  • Depositing WETH for aWETH shares in Aave V2 (second action)

Notes:

  • Make sure you've appropriately initialized the NexeraFiSDK, covering configurations essential for further interactions.
  • Ensure that the wallet managed by the microservice is configured as the designated executor for the target Orchestrator instance (see example).
  • Ensure your .env file includes the MICROSERVICE_AUTH_KEY, which should be set to the key provided by the microservice provider, for proper authorization.
const chainId: ChainId = 42161; // Arbitrum One
const orchestratorAddress = "0x..."; // Replace with the address of the instance you own
const microserviceUrl = "http://nexeraFi/execute-transaction"; // Change this to the microservice URL
 
// Target Assets
// Note: Assets at play should be already whitelisted in the `Orchestrator`
const USDC = "0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8";
const WETH = "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1";
const AWETH = "0xe50fA9b3c56FfB159cB0FCA61F5c9D750e8128c8";
 
// Target Adapters (Uniswap & Aave)
// Note: The Adapters should be already whitelisted and properly initialized in the `Orchestrator`
const UniswapAdapter = nexeraFiSdk.getAdapters(chainId).UniswapAdapter;
const AaveAdapter = nexeraFiSdk.getAdapters(chainId).AaveAdapter;
 
// Get the `executeInMicroservice` function 
const executeInMicroservice = nexeraFiSdk.executeInMicroservice();
 
/* ------------------------- 1st action (Deposit DAI/WETH In Uniswap V3) ------------------------- */
 
// Construct `out` & `expectedIn` token compositions, and `extraData`
const minTick = -887220;
const maxTick = 887220;
const fee = 3000; //0.3%
 
const outUniswap = [
	{ token: USDC, amount: ethers.utils.parseUnits("1", 6) }, // 1 USDC
	{ token: WETH, amount: ethers.utils.parseEther("0.0001") }, // 0.0001 WETH
];
const expectedInUniswap = [
	{ token: USDC, amount: ethers.utils.parseEther("0") }, // 0 USDC
	{ token: WETH, amount: ethers.utils.parseEther("0") }, // 0 WETH
];
const extraDataUniswap = ethers.utils.defaultAbiCoder.encode(
	["uint256", "uint24", "int24", "int24"],
	// tokenId = 0, fee = 0.3%, tickLower = min, tickUpper = max
	[0, fee, minTick, maxTick]
);
 
// Populate the action object with the appropriate data
const action1 = {
    adapter: UniswapAdapter.address,
    op: Operation.DEPOSIT,
    send: outUniswap,
    minReceive: expectedInUniswap,
    extraData: extraDataUniswap,
};
 
/* ---------------------- 2nd action (Deposit WETH for aWETH shares In Aave V2) -------------------- */
 
// Construct `out` & `expectedIn` token compositions, and `extraData`
const outAave = [
	{ token: WETH, amount: ethers.utils.parseEther("100") }, // 100 WETH
];
const expectedInAave = [
	{ token: AWETH, amount: "0" } //Minimum amount expected to be received (set to "0" for no limit indication)
];
const extraDataAave = ethers.utils.defaultAbiCoder.encode(
	["tuple(uint)"],
	[[AaveAdapter.operations.DEPOSIT.SUPPLY]]
);
 
// Populate the action object with the appropriate data
const action2 = {
    adapter: AaveAdapter.address,
    op: Operation.DEPOSIT,
    send: outAave,
    minReceive: expectedInAave,
    extraData: extraDataAave,
};
 
/* ----------------------------------- ExecuteInMicroservice ----------------------------- */
// Define the actions to be executed
const actions = [action1, action2];
 
// Number of attemps if Tx fails
const failedCaseTx = 0;
const gasLimit = 1000000;
 
const response = await executeInMicroservice(
    orchestratorAddress,
    actions,
    failedCaseTx,
    microserviceUrl,
	gasLimit,
    chainId
);

On this page