UNPKG

@fairmint/canton-node-sdk

Version:
157 lines 6.97 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.transferToPreapproved = transferToPreapproved; const mining_rounds_1 = require("../mining/mining-rounds"); const get_amulets_for_transfer_1 = require("./get-amulets-for-transfer"); /** * Transfers coins to multiple parties that have pre-approved transfers enabled * * @example * ```typescript * const result = await transferToPreapproved(ledgerClient, validatorClient, { * senderPartyId: 'sender-party-id', * transfers: [ * { * recipientPartyId: 'recipient-1', * amount: '100', * description: 'Payment for services' * }, * { * recipientPartyId: 'recipient-2', * amount: '50', * description: 'Bonus payment' * } * ] * }); * * * ```; * * @param ledgerClient - Ledger JSON API client for submitting commands * @param validatorClient - Validator API client for getting network information * @param params - Parameters for the transfers * @returns Promise resolving to the transfer results */ async function transferToPreapproved(ledgerClient, validatorClient, params) { if (params.transfers.length === 0) { throw new Error('At least one transfer must be provided'); } // Get network information const [amuletRules, miningRoundContext] = await Promise.all([ validatorClient.getAmuletRules(), (0, mining_rounds_1.getCurrentMiningRoundContext)(validatorClient), ]); const { openMiningRound: openMiningRoundContractId } = miningRoundContext; // Get amulet inputs for the sender party const amulets = await (0, get_amulets_for_transfer_1.getAmuletsForTransfer)({ jsonApiClient: ledgerClient, readAs: [params.senderPartyId], }); if (amulets.length === 0) { throw new Error(`No unlocked amulets found for sender party ${params.senderPartyId}`); } // Convert amulets to input format const inputs = amulets.map((amulet) => ({ tag: 'InputAmulet', value: amulet.contractId, })); const transferResults = []; // Build base disclosed contracts (shared across all transfers) const disclosedContracts = [ // AmuletRules contract (required) { contractId: amuletRules.amulet_rules.contract.contract_id, templateId: amuletRules.amulet_rules.contract.template_id, createdEventBlob: amuletRules.amulet_rules.contract.created_event_blob, synchronizerId: amuletRules.amulet_rules.domain_id, }, // Open mining round contract (shared) { contractId: miningRoundContext.openMiningRoundContract.contractId, templateId: miningRoundContext.openMiningRoundContract.templateId, createdEventBlob: miningRoundContext.openMiningRoundContract.createdEventBlob, synchronizerId: miningRoundContext.openMiningRoundContract.synchronizerId, }, ]; // Process each transfer for (const transfer of params.transfers) { // Look up transfer preapproval for the recipient const transferPreapprovalResponse = await validatorClient.lookupTransferPreapprovalByParty({ partyId: transfer.recipientPartyId, }); const { transfer_preapproval } = transferPreapprovalResponse; const transferPreapprovalContract = transfer_preapproval.contract; const transferPreapprovalContractId = transferPreapprovalContract.contract_id; if (!transfer_preapproval.domain_id) { throw new Error(`No domain ID found for transfer preapproval for party ${transfer.recipientPartyId}`); } // Look up featured app right for the recipient const featuredAppRight = await validatorClient.lookupFeaturedAppRight({ partyId: transfer.recipientPartyId, }); if (!featuredAppRight.featured_app_right?.contract_id) { throw new Error(`No featured app right found for party ${transfer.recipientPartyId}`); } const featuredAppRightContractId = featuredAppRight.featured_app_right.contract_id; // Build transfer-specific disclosed contracts const transferDisclosedContracts = [ ...disclosedContracts, // Include base contracts // Featured app right contract for this recipient { contractId: featuredAppRight.featured_app_right.contract_id, templateId: featuredAppRight.featured_app_right.template_id, createdEventBlob: featuredAppRight.featured_app_right.created_event_blob, synchronizerId: amuletRules.amulet_rules.domain_id, }, // Transfer preapproval contract for this recipient { contractId: transferPreapprovalContractId, templateId: transferPreapprovalContract.template_id, createdEventBlob: transferPreapprovalContract.created_event_blob, synchronizerId: transferPreapprovalResponse.transfer_preapproval.domain_id, }, ]; // Create the transfer command using TransferPreapproval_Send const transferCommand = { ExerciseCommand: { templateId: '#splice-amulet:Splice.AmuletRules:TransferPreapproval', contractId: transferPreapprovalContractId, choice: 'TransferPreapproval_Send', choiceArgument: { context: { amuletRules: amuletRules.amulet_rules.contract.contract_id, context: { openMiningRound: openMiningRoundContractId, issuingMiningRounds: [], validatorRights: [], featuredAppRight: featuredAppRightContractId, }, }, inputs, amount: transfer.amount, sender: params.senderPartyId, description: transfer.description ?? null, }, }, }; if (!amuletRules.amulet_rules.domain_id) { throw new Error('Amulet rules domain ID is required'); } // Submit the command const submitParams = { commands: [transferCommand], commandId: `transfer-preapproved-${transfer.recipientPartyId}-${Date.now()}`, actAs: [params.senderPartyId], disclosedContracts: transferDisclosedContracts, }; const result = await ledgerClient.submitAndWaitForTransactionTree(submitParams); transferResults.push({ recipientPartyId: transfer.recipientPartyId, contractId: transferPreapprovalContractId, domainId: amuletRules.amulet_rules.domain_id, transferResult: result, }); } return { transferResults }; } //# sourceMappingURL=transfer-to-preapproved.js.map