UNPKG

@fairmint/canton-node-sdk

Version:
137 lines 6.25 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getAmuletsForTransfer = getAmuletsForTransfer; /** * Gets unlocked amulets owned by the sender party that can be used for transfers. Optionally returns all valid transfer * inputs (Amulet, AppRewardCoupon, ValidatorRewardCoupon). * * @param params - Parameters for getting transfer inputs * @returns Promise resolving to array of transfer inputs suitable for transfer */ async function getAmuletsForTransfer(params) { const { jsonApiClient, readAs, includeAllTransferInputs } = params; // Query ledger for active contracts for this party if (!readAs?.[0]) { return []; } const senderParty = readAs[0]; // Build template IDs to query based on includeAllTransferInputs flag const templateIds = includeAllTransferInputs ? [ '#splice-amulet:Splice.Amulet:Amulet', '#splice-amulet:Splice.Amulet:AppRewardCoupon', '#splice-amulet:Splice.Amulet:ValidatorRewardCoupon', ] : ['#splice-amulet:Splice.Amulet:Amulet']; const activeContracts = await jsonApiClient.getActiveContracts({ parties: [senderParty], templateIds, }); const allContracts = []; const contractsArr = Array.isArray(activeContracts) ? activeContracts : []; contractsArr.forEach((ctr) => { const typedCtr = ctr; let payload; let templateId; let contractId; if ('contractEntry' in typedCtr && 'JsActiveContract' in typedCtr.contractEntry) { const { createdEvent } = typedCtr.contractEntry.JsActiveContract; payload = createdEvent.createArgument; ({ templateId, contractId } = createdEvent); } else if ('contract' in typedCtr) { const { contract } = typedCtr; ({ payload } = contract); templateId = contract.contract?.template_id ?? contract.template_id; contractId = contract.contract?.contract_id ?? contract.contract_id; } if (!payload || !templateId || !contractId) return; // Filter for valid transfer input contracts const isUnlockedAmulet = templateId.includes('Splice.Amulet:Amulet') && !templateId.includes('LockedAmulet'); const isAppRewardCoupon = templateId.includes('AppRewardCoupon'); const isValidatorRewardCoupon = templateId.includes('ValidatorRewardCoupon'); if (!isUnlockedAmulet && !isAppRewardCoupon && !isValidatorRewardCoupon) return; allContracts.push({ contractId, templateId, payload }); }); // Helper to extract owner/beneficiary and numeric amount from diverse contract shapes const extract = (contract) => { const contractPayload = 'payload' in contract ? contract.payload : undefined; const payload = contractPayload ?? contract.contract?.contract?.payload ?? {}; const contractRecord = contract; const templateId = 'templateId' in contract ? contract.templateId : undefined; // Extract owner/beneficiary based on contract type let ownerFull = ''; if (templateId?.includes('AppRewardCoupon') || templateId?.includes('ValidatorRewardCoupon')) { // For coupons, beneficiary is optional and falls back to provider const beneficiary = payload['beneficiary']; const provider = payload['provider']; ownerFull = beneficiary ?? provider ?? ''; } else { // For amulets, use owner field ownerFull = payload['owner'] ?? contractRecord['owner'] ?? contractRecord['partyId'] ?? contractRecord['party_id'] ?? ''; } // Extract amount based on contract type let rawAmount = '0'; if (templateId?.includes('AppRewardCoupon') || templateId?.includes('ValidatorRewardCoupon')) { // For coupons, amount is directly in payload rawAmount = payload['amount'] ?? '0'; } else { // For amulets, amount might be nested const rawAmountCandidate = payload['amount'] ?? contractRecord['amount'] ?? contractRecord['effective_amount'] ?? contractRecord['effectiveAmount'] ?? contractRecord['initialAmount'] ?? '0'; rawAmount = rawAmountCandidate; if (typeof rawAmountCandidate === 'object') { rawAmount = rawAmountCandidate['initialAmount'] ?? '0'; } } const numericAmount = parseFloat(rawAmount); return { owner: ownerFull, numericAmount }; }; // Filter contracts owned by sender (readAs[0]) and with positive balance const partyContracts = allContracts.filter((c) => { const { owner, numericAmount } = extract(c); return numericAmount > 0 && owner === senderParty; }); if (partyContracts.length === 0) { return []; } // Sort biggest → smallest so we pick high-value contracts first partyContracts.sort((a, b) => extract(b).numericAmount - extract(a).numericAmount); // Map to the structure expected by buildAmuletInputs (maintaining backward compatibility) const result = partyContracts.map((c) => { const { payload, templateId } = c; // Extract amount based on contract type let effectiveAmount = '0'; if (templateId.includes('AppRewardCoupon') || templateId.includes('ValidatorRewardCoupon')) { // For coupons, amount is directly in payload effectiveAmount = payload['amount'] ?? '0'; } else { // For amulets, amount might be nested const amtObj = payload['amount'] ?? {}; const intAmount = typeof amtObj === 'object' ? amtObj['initialAmount'] : amtObj; effectiveAmount = intAmount ?? '0'; } return { contractId: c.contractId, templateId: c.templateId, effectiveAmount, owner: extract(c).owner, }; }); return result; } //# sourceMappingURL=get-amulets-for-transfer.js.map