A repo demonstrating the use of DeFiActions connectors to create composable workflows
ℹ️ Be sure to install Flow CLI before continuing
Update the FlowActions submodule
git submodule update --init --recursiveInstall dependencies
flow deps installRun emulator
flow emulatorIn another terminal window, run the local setup script
sh local/setup_emulator.shThe TransmitTokensWorkflow contract defines a simple resource
Transmitter that performs a simple function transmitTokens(). This method will transfer tokens from a tokenOrigin: {DeFiActions.Sink, DeFiActions.Source} to a tokenDestination: {DeFiActions.Sink} up to either the capacity of
tokenDestination or the configured maxAmount.
access(all) resource Transmitter {
/// Provides tokens to move - composite connector so any excess withdrawals can be re-deposited
access(self) let tokenOrigin: {DeFiActions.Sink, DeFiActions.Source}
/// Sink to which source tokens are deposited - a SwapSink would swap into a target denomination
access(self) let tokenDestination: {DeFiActions.Sink}
/// The amount of tokens to withdraw from tokenOrigin when executed. If `nil`, transmission amount is whatever
/// the tokenOrigin reports as available. Note that this is the amount of tokens withdrawn, not a dollar value.
/// If this were taken to production, it might be considered to include a PriceOracle to ensure a dollar value
/// is transferred on execution instead of a token amount.
access(self) let maxAmount: UFix64?
// ...
}While simple enough on its own, the Transmitter along with the executing transmit_tokens.cdc
transaction can be used to execute a variety of DeFi workflows. The variety
and flexibility of this object is highly configurable by choice of DeFiAction connectors - tokenOrigin and
tokenDestination.
The following two workflows are just two examples of the sorts of workflows that can be composed and preserved for future execution with existing DeFiActions connectors.
The simplest DeFiActions workflow to configure in the Transmitter is a token transfer. Run the following commands to
configure a FLOW transfer between accounts:
-
Create a recipient account
flow accounts create # follow the prompts, naming the account `emulator-recipient` -
Configure the
Transmitterto send10.0FLOW from the signingemulator-accountto the account that was just created wheneverTransmitter.transmitTokens()is called:flow transactions send cadence/transactions/setup_simple_transmitter.cdc /storage/SimpleFlowTransmitter \ 'A.0ae53cb6e3f42a79.FlowToken.Vault' \ 0xf3fcd2c1a78f5eee \ # should be the address of the account created in step 1. 10.0 -
Now you're ready to run the DeFiActions worfklow stored in the new
Transmitterresource created & stored in step 2.flow transactions send cadence/transactions/transmit_tokens.cdc \ /storage/SimpleFlowTransmitter \ 10.0
After executing, you should see events denoting the withdrawal of 10.0 FLOW from 0xf8d6e0586b0a20c7 and a deposit to
the recipient's account 0xf3fcd2c1a78f5eee.
🎉 You've just composed & executed your first DeFiActions workflow! But we can do a bit better...
Let's up the complexity. We'll withdraw FLOW as we originally did, but this time we'll swap via IncrementFi's AMM protocol ultimately setting up a swap workflow swapping from FLOW to TokenA.
-
Configure the
Transmitterto swap10.0FLOW to TokenA (executed at the price at time of swap) and deposit the resulting TokenA to the same account. The transaction args included in this execution configure theTransmitterto swap10.0at a time until the TokenA balance reached10_000.0(or the originating FLOW vault runs out).flow transactions send cadence/transactions/setup_increment_swap_transmitter.cdc \ /storage/SwapFlowTransmitter \ 10.0 \ 10000.0 -
Now you're ready to execute the workflow. We do this by executing the same transaction as in the simple workflow, just on a different
Transmitterin storage.flow transactions send cadence/transactions/transmit_tokens.cdc \ /storage/SwapFlowTransmitter \ 10.0
Looking at the resulting events, you'll see a similar FLOW withdrawal of 10.0 tokens originating from
0xf8d6e0586b0a20c7. But continuing, you'll notice that along the way, the tokens are swapped into TokenA before
ultimately being deposited to 0xf8d6e0586b0a20c7.
Now that you've run transactions composing a DeFiActions workflow, stored and then that workflow, it's time for you to
extend this basic example. Here are some ideas for how you might extend the simple Transmitter to do even more:
- Automate Transmission - Update
Transmitterto conform toFlowScheduledTransactions.TransactionHandlerto it can be used in scheduled transactions. Even better if the execution of a scheduled transaction sets up another future execution. This allows any configured workflow to be run on a time interval, like an onchain cron job! - Onchain DCA Agent - Assuming you've refactored
Transmitterfor scheduled & recurring execution per the previous point, configure the IncrementFi Swap Workflow to create a dollar-cost averaging workflow, swapping one token for another on a time interval. - Compound Staking Rewards - Create a staking reward
{DeFiActions.Sink, DeFiActions.Source}and a staking{DeFiActions.Sink}and configure theTransmitterso thattransmitTokens()executes an atomic restaking of rewards. Coupled with scheduled transactions, you've enabled automated compounding for anyone with your configuredTransmitter.