@fairmint/canton-node-sdk
Version:
Canton Node SDK
120 lines • 5.44 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.preApproveTransfers = preApproveTransfers;
const mining_rounds_1 = require("../mining/mining-rounds");
const get_amulets_for_transfer_1 = require("./get-amulets-for-transfer");
/**
* Creates a TransferPreapproval contract to enable pre-approved transfers for a party
*
* @param ledgerClient - Ledger JSON API client for submitting commands
* @param validatorClient - Validator API client for getting network information
* @param params - Parameters for creating the pre-approval
* @returns Promise resolving to the pre-approval result
*/
async function preApproveTransfers(ledgerClient, validatorClient, params) {
// Set default expiration to 1 year from now if not provided
const expiresAt = params.expiresAt ?? new Date(Date.now() + 365 * 24 * 60 * 60 * 1000);
// Use receiverPartyId as provider if not specified
const providerPartyId = params.providerPartyId ?? params.receiverPartyId;
// Get network information
const [amuletRules, dsoPartyId, miningRoundContext, featuredAppRight] = await Promise.all([
validatorClient.getAmuletRules(),
validatorClient.getDsoPartyId(),
(0, mining_rounds_1.getCurrentMiningRoundContext)(validatorClient),
validatorClient.lookupFeaturedAppRight({ partyId: params.receiverPartyId }),
]);
// Derive current mining round context (handles opensAt logic)
const { openMiningRound: openMiningRoundContractId, openMiningRoundContract } = miningRoundContext;
// Build disclosed contracts array directly
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
{
contractId: openMiningRoundContract.contractId,
templateId: openMiningRoundContract.templateId,
createdEventBlob: openMiningRoundContract.createdEventBlob,
synchronizerId: openMiningRoundContract.synchronizerId,
},
];
// Add featured app right contract if found
if (featuredAppRight.featured_app_right) {
disclosedContracts.push({
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,
});
}
// Get amulet inputs for the receiver party
const amulets = await (0, get_amulets_for_transfer_1.getAmuletsForTransfer)({
jsonApiClient: ledgerClient,
readAs: [params.receiverPartyId],
});
if (amulets.length === 0) {
throw new Error(`No unlocked amulets found for provider party ${params.receiverPartyId}`);
}
// Convert amulets to input format
const inputs = amulets.map((amulet) => ({
tag: 'InputAmulet',
value: amulet.contractId,
}));
// Create the TransferPreapproval contract using AmuletRules_CreateTransferPreapproval
const createCommand = {
ExerciseCommand: {
templateId: amuletRules.amulet_rules.contract.template_id,
contractId: amuletRules.amulet_rules.contract.contract_id,
choice: 'AmuletRules_CreateTransferPreapproval',
choiceArgument: {
context: {
amuletRules: amuletRules.amulet_rules.contract.contract_id,
context: {
openMiningRound: openMiningRoundContractId,
issuingMiningRounds: [],
validatorRights: [],
featuredAppRight: featuredAppRight.featured_app_right?.contract_id ?? null,
},
},
inputs,
receiver: params.receiverPartyId,
provider: providerPartyId,
expiresAt: expiresAt.toISOString(),
expectedDso: dsoPartyId.dso_party_id,
},
},
};
// Submit the command
const submitParams = {
commands: [createCommand],
commandId: `create-preapproval-${Date.now()}`,
actAs: [params.receiverPartyId],
disclosedContracts,
};
const result = await ledgerClient.submitAndWaitForTransactionTree(submitParams);
// Extract the created TransferPreapproval contract ID from the result
const events = result.transactionTree.eventsById;
let contractId;
for (const eventKey in events) {
const event = events[eventKey];
if (event &&
'CreatedTreeEvent' in event &&
event.CreatedTreeEvent.value.templateId.includes('TransferPreapproval')) {
({ contractId } = event.CreatedTreeEvent.value);
break;
}
}
if (!contractId) {
throw new Error('Failed to create TransferPreapproval contract');
}
return {
contractId,
domainId: amuletRules.amulet_rules.domain_id,
amuletPaid: '0', // This would be extracted from the transfer result
};
}
//# sourceMappingURL=pre-approve-transfers.js.map