A template project demonstrating best practices for building Agoric smart contracts with orchestration flows and durable state.
src/
contract.js # Main contract entry point
flows.js # Orchestration flows
exos/
greeter-kit.js # Durable ExoClassKit example
utils/
helpers.js # Pure utility functions
zoe.js # Zoe-related utilities
typeGuards.js # Endo pattern shapes and interfaces
test/
contract.test.js # Contract integration tests
supports.js # Test setup utilities
exos/
greeter-kit.test.js # Unit tests for the kit
The contract follows the orchestration pattern:
export const contract = async (zcf, privateArgs, zone, tools) => {
// Contract setup using zone for durable state
// Returns { creatorFacet, publicFacet }
};
export const start = withOrchestration(contract);Demonstrates creating durable objects with multiple facets:
- holder: Main functionality (greeting)
- invitationMakers: Creates Zoe invitations for capability-based access
- admin: Administrative controls
export const prepareGreeterKit = (zone, powers) => {
return zone.exoClassKit('GreeterKit', GreeterKitI, initFn, {
holder: { /* methods */ },
invitationMakers: { /* methods */ },
admin: { /* methods */ },
});
};Uses Endo patterns for runtime type validation:
export const GreeterKitI = harden({
holder: M.interface('GreeterHolder', {
greet: M.call(M.string()).returns(GreetingResultShape),
}),
// ...
});Shows how to define async orchestration flows:
export const makeLocalAccount = async (orch) => {
const agoricChain = await orch.getChain('agoric');
return agoricChain.makeAccount();
};Demonstrates creating invitations for capability-based access:
const greetHandler = (seat, { name }) => {
const result = mainGreeter.holder.greet(name);
seat.exit();
return result;
};
return zcf.makeInvitation(greetHandler, 'greet');# Run all tests
yarn test
# Run with coverage
yarn test:c8
# Run linting
yarn lint
# Fix linting issues
yarn lint-fixState must be hardened and arrays cannot be mutated in place:
// Wrong - will fail
state.history.push(name);
// Correct - replace the array
state.history = harden([...state.history, name]);Use zone.makeOnce for durable singletons:
const mainGreeter = zone.makeOnce('MainGreeter', () =>
makeGreeterKit('main', greeting),
);Use inert invitations as receipts for completed actions:
const makeInertInvitation = defineInertInvitation(zcf, 'action performed');| File | Purpose |
|---|---|
contract.js |
Contract setup, facet definitions, initialization |
flows.js |
Orchestration flow functions |
exos/greeter-kit.js |
Durable exoClassKit with facets |
utils/helpers.js |
Pure utility functions |
utils/zoe.js |
Zoe-related utilities |
typeGuards.js |
Type validation patterns |
@agoric/orchestration- Cross-chain orchestration@agoric/zoe- Smart contract framework@agoric/zone- Durable state management@endo/patterns- Runtime type validation@endo/errors- Error handling utilities
Apache-2.0