preApproveTransfers stitches validatorClient reads (getAmuletRules, getDsoPartyId, getCurrentMiningRoundContext, lookupFeaturedAppRight) into submitAndWaitForTransactionTree exercised by readAs[0] (receiverPartyId). It pulls unlocked inputs via getAmuletsForTransfer for the receiver party and retries 409 LOCAL_VERDICT_LOCKED_CONTRACTS up to three times with exponential backoff.
Setup
import { preApproveTransfers } from '@fairmint/canton-node-sdk';
const canton = new Canton({
network: 'NETWORK_NAME',
partyId: 'PARTY_ID',
});
Minimal example
const result = await preApproveTransfers(canton.ledger, canton.validator, {
receiverPartyId: 'RECEIVER_PARTY_ID',
});
console.log(result.contractId, result.domainId);
Parameters
PreApproveTransfersParams:
receiverPartyId(required, string) — Party receiving prepaid transfers — must match ledgeractAsfor submission.providerPartyId(optional) — Defaults toreceiverPartyIdwhen omitted.expiresAt(optional,Date) — Expiration timestamp for the preapproval record (defaults one year ahead).contractDetails(optional) — Rare escape hatch if you already fetched blobs manually; normally omit so validators populate disclosures.
Ledger and validator clients are positional arguments (ledgerClient, validatorClient) ahead of params.
Returns
Promise<PreApproveTransfersResult> with contractId, domainId, amuletPaid (currently '0' placeholder in SDK).
Errors
OperationErrorwithINSUFFICIENT_FUNDSwhen no unlocked Amulets exist forreceiverPartyId.OperationErrorTRANSACTION_FAILEDwhen tree parsing cannot locateTransferPreapprovalcreation.- Propagates
ApiError/ValidationErrorfrom nested helpers.
Auth and party
Submits as receiverPartyId (actAs). Receiver must already hold spendable Amulets because onboarding pays fees through AmuletRules_CreateTransferPreapproval.
See also
createParty— bundles onboarding funding plus preapproval.transferToPreapproved— consumes existing preapprovals.