Modules & Imports¶
StxScript supports a module system for organizing code across files and making inter-contract calls.
Import Syntax¶
Import declarations bring symbols from other modules into scope:
import { TokenTrait } from "./traits";
import { utils } from "../lib/utils";
import { SIP010 } from "@sips/sip-010";
Import Forms¶
// Named imports
import { Transfer, Mint } from "./events";
// Module import
import { math } from "./lib/math";
Imports are resolved relative to the current file or from packages.
Contract Calls¶
Call functions on other deployed contracts using dot notation:
let result = OtherContract.transfer(sender, recipient, amount);
let balance = TokenContract.get_balance(account);
Generated Clarity:
(contract-call? .OtherContract transfer sender recipient amount)
(contract-call? .TokenContract get-balance account)
Handling Contract Call Results¶
Contract calls return Response types that should be handled:
@public
function swap(amount: uint): Response<bool, uint> {
// Use try! to propagate errors
let transferred = try!(TokenA.transfer(tx-sender, contract_address, amount));
// Or match explicitly
match TokenB.transfer(contract_address, tx-sender, amount) {
ok(success) => ok(true),
err(code) => err(code)
}
}
Fully Qualified Contract References¶
For contracts deployed at specific addresses:
let result = 'SP2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKNRV9EJ7.token-contract.transfer(
tx-sender,
recipient,
amount
);
Generated Clarity:
(contract-call? 'SP2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKNRV9EJ7.token-contract
transfer tx-sender recipient amount)
Module Organization¶
Single Contract Per File¶
The recommended pattern is one contract per .stx file:
src/
├── token.stx # Main token contract
├── governance.stx # Governance contract
├── traits/
│ ├── sip-010.stx # SIP-010 trait definition
│ └── ownable.stx # Ownable trait
└── lib/
└── math.stx # Utility functions
Trait Modules¶
Define traits in separate files for reuse:
// traits/sip-010.stx
trait SIP010 {
transfer(amount: uint, sender: principal, recipient: principal, memo: Optional<buffer<34>>): Response<bool, uint>;
get_balance(account: principal): Response<uint, uint>;
get_total_supply(): Response<uint, uint>;
}
// token.stx
import { SIP010 } from "./traits/sip-010";
@implements(SIP010)
contract MyToken {
// ...
}
Inter-Contract Patterns¶
Proxy Pattern¶
@public
function proxy_transfer(token: principal, to: principal, amount: uint): Response<bool, uint> {
let result = try!(TokenContract.transfer(amount, tx-sender, to, none));
return ok(result);
}
Callback Pattern¶
@public
function execute_with_callback(action: uint): Response<bool, uint> {
// Perform action
let result = try!(perform_action(action));
// Notify callback contract
try!(CallbackContract.on_action_complete(action, result));
return ok(true);
}
Multi-Contract Composition¶
@public
function complex_swap(
amount_a: uint,
amount_b: uint
): Response<bool, uint> {
// Step 1: Transfer token A from user
try!(TokenA.transfer(amount_a, tx-sender, contract_address, none));
// Step 2: Transfer token B to user
try!(TokenB.transfer(amount_b, contract_address, tx-sender, none));
return ok(true);
}
Next Steps¶
- Traits - Defining contract interfaces
- Functions - Public function signatures
- Error Handling - Handling inter-contract errors