Skip to main content
Every state-changing operation in the Modo Ledger service uses a two-phase transaction model. This guarantees that the private key never leaves the client, and that the server never submits anything the agent has not explicitly authorised.

Phases

1

Prepare

The client calls PrepareTransaction with a TransactionOperation enum value and a matching params oneof. The server builds the Canton transaction, returns its hash (prepared_transaction_hash), the serialized prepared_transaction, a transaction_id, and a TrafficEstimate.
2

Sign

The client signs prepared_transaction_hash with the agent’s Ed25519 private key — see Authentication for details on how signatures are carried.
3

Execute

The client calls ExecuteTransaction with transaction_id and the hex-encoded signature. The server submits the transaction to Canton and returns the outcome — including update_id, contract_id, any newly created contracts, and the traffic actually consumed.

TransactionOperation

The enum selects which sub-operation the server should build in phase 1:
enum TransactionOperation {
  TRANSACTION_OPERATION_UNSPECIFIED = 0;

  // DvP settlement
  TRANSACTION_OPERATION_PAY_DVP_FEE   = 1;
  TRANSACTION_OPERATION_PROPOSE_DVP   = 2;
  TRANSACTION_OPERATION_ACCEPT_DVP    = 3;
  TRANSACTION_OPERATION_PAY_ALLOC_FEE = 4;
  TRANSACTION_OPERATION_ALLOCATE      = 5;

  // Canton Coin transfers
  TRANSACTION_OPERATION_TRANSFER_CC = 6;

  // Preapproval
  TRANSACTION_OPERATION_REQUEST_PREAPPROVAL = 7;

  // Recurring payments
  TRANSACTION_OPERATION_REQUEST_RECURRING_PREPAID    = 8;
  TRANSACTION_OPERATION_REQUEST_RECURRING_PAYASYOUGO = 9;

  // User service
  TRANSACTION_OPERATION_REQUEST_USER_SERVICE = 10;

  // CIP-56 token transfers
  TRANSACTION_OPERATION_TRANSFER_CIP56 = 11;
  TRANSACTION_OPERATION_ACCEPT_CIP56   = 12;

  // CC merge-split
  TRANSACTION_OPERATION_SPLIT_CC = 13;

  // Atomic batch via Execute_MultiCall DAR choice
  TRANSACTION_OPERATION_EXECUTE_MULTICALL = 14;
}

Operations reference

Each enum value corresponds to one dedicated method page that documents its params message:
Operationparams fieldPage
PAY_DVP_FEEpay_feePayDvpFee
PROPOSE_DVPpropose_dvpProposeDvp
ACCEPT_DVPaccept_dvpAcceptDvp
PAY_ALLOC_FEEpay_feePayAllocFee
ALLOCATEallocateAllocate
TRANSFER_CCtransfer_ccTransferCc
SPLIT_CCsplit_ccSplitCc
REQUEST_PREAPPROVALrequest_preapprovalRequestPreapproval
TRANSFER_CIP56transfer_cip56TransferCip56
ACCEPT_CIP56accept_cip56AcceptCip56
REQUEST_RECURRING_PREPAIDrequest_recurring_prepaidRequestRecurringPrepaid
REQUEST_RECURRING_PAYASYOUGOrequest_recurring_payasyougoRequestRecurringPayasyougo
REQUEST_USER_SERVICErequest_user_serviceRequestUserService
EXECUTE_MULTICALLexecute_multicallExecuteMultiCall

PrepareTransactionRequest

message PrepareTransactionRequest {
  TransactionOperation operation = 1;

  oneof params {
    PayFeeParams                       pay_fee                        = 10;
    ProposeDvpParams                   propose_dvp                    = 11;
    AcceptDvpParams                    accept_dvp                     = 12;
    AllocateParams                     allocate                       = 13;
    TransferCcParams                   transfer_cc                    = 14;
    RequestPreapprovalParams           request_preapproval            = 15;
    RequestRecurringPrepaidParams      request_recurring_prepaid      = 16;
    RequestRecurringPayasyougoParams   request_recurring_payasyougo   = 17;
    RequestUserServiceParams           request_user_service           = 18;
    TransferCip56Params                transfer_cip56                 = 19;
    AcceptCip56Params                  accept_cip56                   = 20;
    SplitCcParams                      split_cc                       = 21;
    ExecuteMultiCallParams             execute_multicall              = 22;
  }

  MessageSignature request_signature = 30;
}

PrepareTransactionResponse

transaction_id
string
Opaque server-assigned ID. Pass this into ExecuteTransaction.
prepared_transaction_hash
string
Hex-encoded Canton transaction hash. This is what the agent must sign.
command_id
string
Canton command ID used for idempotency.
prepared_transaction
bytes
Serialised prepared transaction (for deterministic re-hashing if desired).
hashing_scheme_version
string
Canton hashing scheme version used to compute the hash.
traffic_estimate
TrafficEstimate
Estimated Canton traffic (read_cost, write_cost, total_cost) the transaction will consume.
response_signature
MessageSignature
Provider signature over the response payload — see Authentication.
transaction_status
TransactionStatus
Always PENDING after prepare.

ExecuteTransactionRequest

transaction_id
string
required
Value returned from PrepareTransaction.
signature
string
required
Hex-encoded Ed25519 signature over prepared_transaction_hash.
request_signature
MessageSignature
required
Message-level signature from the cloud agent — see Authentication.

ExecuteTransactionResponse

success
bool
true if the transaction was submitted and committed successfully.
update_id
string
Canton update ID of the committed transaction.
contract_id
string (optional)
Primary contract created by the transaction (if any).
created_contracts
CreatedContractInfo[]
All contracts created by the transaction — useful for tracking new amulets from change/split.
traffic
TrafficEstimate
Actual traffic consumed.
rewards_amount
string (optional)
Featured-app rewards earned, if applicable.
rewards_round
uint64 (optional)
Mining round in which rewards were earned.
error_message
string (optional)
Human-readable error.
provider_error
ProviderError (optional)
Structured error (ProviderRpcError) when success = false.
transaction_status
TransactionStatus
EXECUTED on success, FAILED on error.