Skip to content

Third Party Dependencies

Third party dependencies are external modules that a controlled module interacts with. Typically, these external modules exist under different accounts.

A multi-DEX router actively utilizes third party dependencies. Instead of submitting multiple transactions to interact with different DEXs and their individual entry functions within a swap route, a module (or script) can consolidate all independent DEX invocations into a single, atomic transaction. The multi-DEX router references and calls to functions present in each of the third party DEX modules to achieve this.

Third party dependencies will have varying amounts of reliability and available information based on where they’re sourced from. Specifically, documentation for a few instances will be non-existant, as well as logic potentially being refactored.

Source code that is verified against the on-chain deployed module, like the Git Repository and Local Source Code, should always be preferred. If neither of those are available, there are other options to depend on usable code, like decompiled code, bytecode, and ABI-crafted code.

The default Move.toml includes AptosFramework as a git repository dependency:

[dependencies.AptosFramework]
git = "<https://github.com/aptos-labs/aptos-framework.git>"
rev = "mainnet"
subdir = "aptos-framework"

When Aptos CLI commands are ran, updates to the dependency are automatically retrieved and compiled against.

Third party source code can be included in the sources directory. Essentially treating it the same as custom code.

  • Directorythird_party_dependency_project/
    • Directorysource/
      • {ControlledCode}.move
      • {ThirdPartyCode}.move
    • Move.toml

Move code can be reconstructed by using the Revela Compiler against a package’s bytecode:

Terminal window
aptos move decompile --package-path ./bytecode_modules

Corresponding {ModuleName}.mv.move files will be generated in bytecode_modules.

  • Directorythird_party_dependency_project/
    • Directorybyte_modules/
      • {ModuleName}.mv
      • {ModuleName}.mv.move
    • Move.toml

Reference it as a local source file after changing the file type to {ModuleName}.move and placing it in the workspace’s sources directory.

  • Directorythird_party_dependency_project/
    • Directorysources/
      • {ModuleName}.move
    • Move.toml

The Aptos CLI allows for downloading a package’s bytecode.

Terminal window
aptos move download --account {account_addr} --bytecode --package {package_name}

Each bytecode dependency requires their own package, with a structure of:

  • Move.toml file, with the package address pre-defined.
  • build/{ModuleName}/bytecode_modules directory with the bytecode inside.
  • Empty sources directory.

The controlled module can then reference the dependency, upon it’s inclusion in the controlled package’s Move.toml.

Aptos Token example

A controlled invoking_code.move module interacts with the external aptos_token module:

module invoker::invoking_code {
use aptos_token_objects_addr::aptos_token;
public entry fun wrapper_add_property(): u64 {
aptos_token::add_property(...);
}
}

The below command retrieves the necessary AptosTokenObjects package bytecode from the Mainnet.

Terminal window
aptos move download --account 0x4 \
--bytecode --package AptosTokenObjects \
--output-dir ./aptos_token_bytecode_output/
  • Directoryinvoking_code/
    • Directoryaptos_token_bytecode_output/
      • Directorybyte_modules/
        • aptos_token.mv
    • Directorysources/
      • invoking_code.move
    • Move.toml

The created dependency package structure and contents for aptos_token is:

  • Directoryaptos_token_objects_addr/
    • Directorybuild/
      • Directoryaptos_token/
        • Directorybytecode_modules/
          • aptos_token.mv
    • Directorysources/
    • Move.toml
  • Directoryinvoking_code/
    • Directoryaptos_token_bytecode_output/
      • Directorybyte_modules/
        • aptos_token.mv
        • aptos_token.mv.move
    • Directorysources/
      • invoking_code.move
    • Move.toml
[package]
name = "aptos_token"
version = "0.0.0"
[addresses]
aptos_token_module_addr = "0x4"

The dependency list from the controlled invoking_code.move module will include a local reference to the bytecode package, allowing for compilation.

[package]
name = "invoking_code"
[addresses]
invoker = "_"
[dependencies]
aptos_token = { local = "../aptos_token_objects_addr" }

Move interface code can be manually crafted by reading a package’s ABI. Notably, while the function header is required to be exact, the logic within is not.

Afterwards, the interface code is treated equivalent to local source code.

Aptos Token example

Below is a portion of the AptosTokenObjects ABI, gathered from the Aptos Explorer:

{
"address": "0x4",
"name": "aptos_token",
"friends": [],
"exposed_functions": [
{
"name": "add_property",
"visibility": "public",
"is_entry": true,
"is_view": false,
"generic_type_params": [
{
"constraints": [
"key"
]
}
],
"params": [
"&signer",
"0x1::object::Object<T0>",
"0x1::string::String",
"0x1::string::String",
"vector<u8>"
],
"return": []
},
...
]
}

An interface Move file can be handwritten and treated as a source file. Looking similar to:

module 0x4::aptos_token {
// ...
public entry fun add_property<T: key>(
creator: &signer,
token: Object<T>,
key: String,
type: String,
value: vector<u8>,
) acquires AptosCollection, AptosToken {
abort 0
}
}
  • Directorythird_party_dependency_project/
    • Directorysource/
      • {ControlledCode}.move
      • aptos_token.move
    • Move.toml