The full Airdrop flow uses the DAML Airdrop template: you create a contract with sender / FeaturedAppRight / Amulet rules / DSO configuration, optionally let parties join (with disclosed contract metadata), adjust config and observers, then execute with recipient transfer specs and on-chain Amulet inputs. All helpers return data for ocp.createBatch or an equivalent submit path; they do not call the ledger.
Setup
import { OcpClient } from '@open-captable-protocol/canton';
const ocp = new OcpClient({ ledger: canton.ledger });
Minimal example
const OPERATOR_PARTY = 'OPERATOR_PARTY_ID';
const AIRDROP_CONFIG = {
sender: 'SENDER_PARTY_ID',
featuredAppRight: 'FEATURED_APP_RIGHT_CONTRACT_ID',
amuletRulesCid: 'AMULET_RULES_CONTRACT_ID',
dso: 'DSO_PARTY_ID',
};
const createCmd = ocp.CantonPayments.airdrop.buildCreateAirdropCommand({
config: AIRDROP_CONFIG,
observers: [], // optional extra observer parties
});
await ocp.createBatch({ actAs: [OPERATOR_PARTY] }).addCommand(createCmd).submitAndWaitForTransactionTree();
API (receiver: ocp.CantonPayments.airdrop)
buildCreateAirdropCommand(params)
config(required) —AirdropConfig:sender,featuredAppRight,amuletRulesCid,dso(party / contract id strings as required by your deployment).observers(optional) —string[], default[]. Passed as template create argument observers.
Returns: Canton Command (CreateCommand).
buildUpdateAirdropConfigCommand(params)
airdropContractId(required) — Contract id of the existingAirdrop.newConfig(required) — Same shape asAirdropConfig; emptyfeaturedAppRightbecomesnullin the choice argument.
Returns: Command exercising Airdrop_UpdateConfig.
buildAddObserversToAirdropCommand(params)
airdropContractId(required)actor(required) — Party exercising the choice.newObservers(required) —string[]of party ids to add.
Returns: Command exercising Airdrop_AddObservers.
buildJoinAirdropCommand(params)
airdropContractId(required)actor(required) — Joining party.airdropContractDetails(required) —AirdropContractDetails:templateId,contractId,createdEventBlob,synchronizerIdfrom the airdrop’s created event (for disclosure on the join transaction).
Returns: CommandWithDisclosedContracts — use addBuiltCommand / batch APIs that accept disclosed contracts alongside the exercise.
buildExecuteAirdropCommand(params)
airdropContractId(required)transferSpecs(required) —RecipientTransferSpec[]: eachrecipient,numberOfTransfers,appRewardBeneficiaries(beneficiary,weightasstring | number).initialAmuletInputs(required) —string[]contract ids of input amulets.openMiningRoundCid(required) — Current open mining round contract id.amountPerTransfer(required) —string | number(coerced to string in the choice).amuletRules(required) — Amulet rules contract id (string).
Returns: Command exercising Airdrop_Execute.
Errors
These builders are thin wrappers; they do not throw OcpValidationError / OcpContractError. Submission failures surface from the participant as ledger errors. Misconfigured disclosure on join typically causes authorization or contract visibility errors at submit time.
Auth and disclosure
- Create / update / add observers / execute:
actAsmust include parties authorized for the corresponding DAML choices (usually operator / sender per your model). - Join: Must include the join transaction’s
disclosedContractspayload so validators can see the archived-or-live airdrop creation event as required by your synchronizer setup.