In the src/instructions_data folder, there are structures needed to fill the buffer for specific transactions, and in the src/instructions_data/instructions.rs file, there is a list of available smart contract instructions. However, this is not the most convenient way to compile instructions, so the library provides constructors for instructions and transactions.

Since this SDK is common for the smart contract, client applications, frontend, and administrative tools, you can view all transactions available on the platform. However, you can only execute custom user transactions.

Custom User Transactions

InstructionOptionTrade

Option trading or bucket-based trading. In this instruction, you need to specify the stake size in each bucket (positive number for buying, negative for selling). Optionally, you can also specify:

  • Basket (from zero to 4 positions): if specified, this deal will be reflected in the portfolio on the website (option trading); if not specified, it will not be (bucket trading).
  • Maximum cost of the transaction (the final price may vary slightly at the time of the actual transaction).

InstructionLpTrade

Buying or selling pool tokens (participating in the pool as a liquidity provider). The only parameter is the amount of pool tokens being bought or sold (positive number for buying, negative for selling).

InstructionPayoff

Receiving payout upon the expiration of the pool. Parameters:

  • worker_id: the number of the worker account servicing the pool.
  • pool_id: the sequential number of the pool (expiration). One worker services consecutive pools, so it is necessary to specify the pool number as well.

InstructionTransferToken

Transferring money for trading on the platform.

  • mint_id: unique number of the currency according to MintsAccount (base currency).
  • amount: quantity.

InstructionWithdrawToken

Withdrawing funds from the platform.

  • mint_id: unique number of the currency according to MintsAccount (base currency).
  • amount: quantity.

Instruction Constructor (Data Fields Only)

Similar to reading an account, the library provides an abstract factory for constructing the data buffer of the required instruction, requesting parameters specific to that instruction. There is no need to fill all the data fields yourself - just prepare the specific instruction parameters and call the factory:

let trade_params = OptionTradeParams {
  trade_qty: [0; BUCKETS_COUNT],
  basket: None,
  max_cost: None,
};
let instruction_data = DvlInstruction::new::<InstructionOptionTrade>(trade_params) ?;

Transaction Constructor

Once you have prepared the instruction data, you can either use them to compose the instruction yourself by serializing them using the built-in method to_vec_le:

let serialized_data = instruction_data.to_vec_le();

Preparing the Transaction

After which, you should prepare the transaction.

However, the recommended method is using the as_transaction_instruction. Let’s consider a complete basic example of constructing a transaction from the moment of creating a DvlClient instance to getting a transaction ready for sending:

// Construct Devol client:
let rpc_client = RpcClient::new(String::from(RPC_URL));
let dvl_client = DvlClient::new(rpc_client, INT_SEED, ADMIN_PUBLIC_KEY, PROGRAM_ID);
// Construct instruction data:
let trade_params = OptionTradeParams {
  trade_qty: [0; BUCKETS_COUNT],
  basket: None,
  max_cost: None,
};
let instruction_data = DvlInstruction::new::<InstructionOptionTrade>(trade_params) ?;
// Get signer Keypair object
let signer_kp = Keypair::from_base58_string(SIGNER_PRIVATE_KEY);
// Construct trade params
let trade_params = OptionTradeDebugTransactionParams {
  client_key: signer_kp.pubkey(),
  worker_id: id_worker,
};
let instruction = instruction_data.as_transaction_instruction(dvl_client, & signer_kp, trade_params).await?;

Using the as_transaction_instruction Method

The as_transaction_instruction method is available on any object derived from DvlInstruction. It takes DvlClient as an argument to specify the transaction with the correct account keys, as these keys are PDAs (Program Derived Addresses) and are linked to a specific branch of the smart contract.

Sending the Transaction

Once you have the instruction, you need to add it to the final transaction and send it via the RPC client (you can use the one passed to DvlClient). If desired, you can use the built-in method for sending transactions, but it is provided “as is,” and most likely, you will want to write your own:

let mut instructions = Vec::<Instruction>::new();
instructions.push( * instruction);
let signature = client.send_transaction(DvlSendTransactionParams {
  instructions,
  signer_kp,
  commitment_config: Some(CommitmentConfig::finalized()),
  compute_budget: Some(1400000),
  compute_unit_price: Some(150),
  verbose: Some(true),
  max_retries: Some(5),
  log_prefix: Some("[TRADE_TRANSACTION] "),
  retry_delay: None,
}).await?;