filecoin-pin
Version:
Bridge IPFS content to Filecoin Onchain Cloud using familiar tools
424 lines • 16.5 kB
TypeScript
/**
* Synapse SDK Payment Operations
*
* This module demonstrates comprehensive payment operations using the Synapse SDK,
* providing patterns for interacting with the Filecoin Onchain Cloud payment
* system (Filecoin Pay).
*
* Key concepts demonstrated:
* - Native FIL balance checking for gas fees
* - ERC20 token (USDFC) balance management
* - Two-step deposit process (approve + deposit)
* - Service approval configuration for storage operators
* - Storage capacity calculations from pricing
*
* @module synapse/payments
*/
import { type Synapse } from '@filoz/synapse-sdk';
import type { PaymentStatus, ServiceApprovalStatus, StorageAllowances, StorageRunwaySummary } from './types.js';
export * from './constants.js';
export * from './floor-pricing.js';
export * from './top-up.js';
export * from './types.js';
/**
* Compute adaptive integer scaling for a TiB value so that
* Math.floor(storageTiB * scale) stays within Number.MAX_SAFE_INTEGER.
* This allows us to handle numbers as small as 1/10_000_000 TiB and as large as Number.MAX_SAFE_INTEGER TiB (> 1 YiB)
*/
export declare function getStorageScale(storageTiB: number): number;
/**
* Check FIL balance for gas fees
*
* Example usage:
* ```typescript
* const synapse = await Synapse.create({ privateKey, rpcURL })
* const filStatus = await checkFILBalance(synapse)
*
* if (filStatus.balance === 0n) {
* console.log('Account does not exist on-chain or has no FIL')
* } else if (!filStatus.hasSufficientGas) {
* console.log('Insufficient FIL for gas fees')
* }
* ```
*
* @param synapse - Initialized Synapse instance
* @returns Balance information and network type
*/
export declare function checkFILBalance(synapse: Synapse): Promise<{
balance: bigint;
isCalibnet: boolean;
hasSufficientGas: boolean;
}>;
/**
* Check USDFC token balance in wallet
*
* Example usage:
* ```typescript
* const synapse = await Synapse.create({ privateKey, rpcURL })
* const walletUsdfcBalance = await checkUSDFCBalance(synapse)
*
* if (walletUsdfcBalance === 0n) {
* console.log('No USDFC tokens found')
* } else {
* const formatted = ethers.formatUnits(walletUsdfcBalance, USDFC_DECIMALS)
* console.log(`USDFC Balance: ${formatted}`)
* }
* ```
*
* @param synapse - Initialized Synapse instance
* @returns bigint USDFC balance in wallet (0 if account doesn't exist or has no balance)
*/
export declare function checkUSDFCBalance(synapse: Synapse): Promise<bigint>;
/**
* Get deposited USDFC balance in Payments contract
*
* This is different from wallet balance - it's the amount
* already deposited and available for payment rails.
*
* @param synapse - Initialized Synapse instance
* @returns Deposited USDFC balance in its smallest unit
*/
export declare function getDepositedBalance(synapse: Synapse): Promise<bigint>;
/**
* Get current payment status including all balances and approvals
*
* Example usage:
* ```typescript
* const status = await getPaymentStatus(synapse)
* console.log(`Address: ${status.address}`)
* console.log(`FIL Balance: ${ethers.formatEther(status.filBalance)}`)
* console.log(`USDFC Balance: ${ethers.formatUnits(status.walletUsdfcBalance, 18)}`)
* console.log(`Deposited: ${ethers.formatUnits(status.filecoinPayBalance, 18)}`)
* ```
*
* @param synapse - Initialized Synapse instance
* @returns Complete payment status
*/
export declare function getPaymentStatus(synapse: Synapse): Promise<PaymentStatus>;
export interface PaymentValidationResult {
isValid: boolean;
errorMessage?: string;
helpMessage?: string;
}
export declare function validatePaymentRequirements(hasSufficientGas: boolean, walletUsdfcBalance: bigint, isCalibnet: boolean): PaymentValidationResult;
/**
* Deposit USDFC into the Payments contract
*
* This demonstrates the single-step process required for depositing ERC20 tokens:
* 1. If approval is insufficient, use permit to approve and deposit in one transaction
* 2. If approval is sufficient, directly call deposit
*
* Example usage:
* ```typescript
* const amountToDeposit = ethers.parseUnits('100', 18) // 100 USDFC
* const { depositTx } = await depositUSDFC(synapse, amountToDeposit)
* console.log(`Deposit transaction: ${depositTx}`)
* ```
*
* @param synapse - Initialized Synapse instance
* @param amount - Amount to deposit in USDFC (with decimals)
* @returns Transaction hashes for approval and deposit
*/
export declare function depositUSDFC(synapse: Synapse, amount: bigint): Promise<{
depositTx: string;
}>;
/**
* Withdraw USDFC from the Payments contract back to the wallet
*
* Example usage:
* ```typescript
* const amountToWithdraw = ethers.parseUnits('10', 18) // 10 USDFC
* const txHash = await withdrawUSDFC(synapse, amountToWithdraw)
* console.log(`Withdraw transaction: ${txHash}`)
* ```
*
* @param synapse - Initialized Synapse instance
* @param amount - Amount to withdraw in USDFC (with decimals)
* @returns Transaction hash for the withdrawal
*/
export declare function withdrawUSDFC(synapse: Synapse, amount: bigint): Promise<string>;
/**
* Set service approvals for WarmStorage operator
*
* This authorizes the WarmStorage contract to create payment rails on behalf
* of the user. The approval consists of three parameters:
* - Rate allowance: Maximum payment rate per epoch (30 seconds)
* - Lockup allowance: Maximum funds that can be locked at once
* - Max lockup period: How far in advance funds can be locked (in epochs)
*
* Example usage:
* ```typescript
* // Allow up to 10 USDFC per epoch rate, 1000 USDFC total lockup
* const rate = ethers.parseUnits('10', 18)
* const lockup = ethers.parseUnits('1000', 18)
* const txHash = await setServiceApprovals(synapse, rate, lockup)
* console.log(`Approval transaction: ${txHash}`)
* ```
*
* @param synapse - Initialized Synapse instance
* @param rateAllowance - Maximum rate per epoch in USDFC
* @param lockupAllowance - Maximum lockup amount in USDFC
* @returns Transaction hash
*/
export declare function setServiceApprovals(synapse: Synapse, rateAllowance: bigint, lockupAllowance: bigint): Promise<string>;
/**
* Check if WarmStorage allowances are at maximum
*
* This function checks whether the current allowances for WarmStorage
* are already set to maximum values (effectively infinite).
*
* @param synapse - Initialized Synapse instance
* @returns Current allowances and whether they need updating
*/
export declare function checkAllowances(synapse: Synapse): Promise<{
needsUpdate: boolean;
currentAllowances: ServiceApprovalStatus;
}>;
/**
* Result of setting maximum allowances for WarmStorage
*/
export interface SetMaxAllowancesResult {
/** Transaction hash of the allowance update */
transactionHash: string;
/** Updated allowance status after the transaction */
currentAllowances: ServiceApprovalStatus;
}
/**
* Set WarmStorage allowances to maximum
*
* This function sets the allowances for WarmStorage to maximum values,
* effectively treating it as a fully trusted service.
*
* @param synapse - Initialized Synapse instance
* @returns Transaction hash and updated allowances
*/
export declare function setMaxAllowances(synapse: Synapse): Promise<SetMaxAllowancesResult>;
/**
* Check and automatically set WarmStorage allowances to maximum if needed
*
* This function treats WarmStorage as a fully trusted service and ensures
* that rate and lockup allowances are always set to maximum values.
* This simplifies the user experience by removing the need to understand
* and configure complex allowance settings by assuming that WarmStorage
* can be fully trusted to manage payments on the user's behalf.
*
* The function will:
* 1. Check current allowances for WarmStorage
* 2. If either is not at maximum, update them to MAX_UINT256
* 3. Return information about what was done
*
* **Session Key Authentication**: When using session key authentication,
* this function will not attempt to update allowances since payment
* operations require the owner wallet to sign. The function will return
* `updated: false` and current allowances, which may not be at maximum.
*
* Example usage:
* ```typescript
* // Call before any operation that requires payments
* const result = await checkAndSetAllowances(synapse)
* if (result.updated) {
* console.log(`Allowances updated: ${result.transactionHash}`)
* }
* ```
*
* @param synapse - Initialized Synapse instance
* @returns Result indicating if allowances were updated and transaction hash if applicable
*/
export declare function checkAndSetAllowances(synapse: Synapse): Promise<{
updated: boolean;
transactionHash?: string;
currentAllowances: ServiceApprovalStatus;
}>;
/**
* Calculate storage allowances from TiB per month
*
* This utility converts human-friendly storage units (TiB/month) into the
* epoch-based rates required by the payment system. It uses the actual
* pricing from the storage service to calculate accurate allowances.
*
* Example usage:
* ```typescript
* const storageInfo = await synapse.storage.getStorageInfo()
* const pricing = storageInfo.pricing.noCDN.perTiBPerEpoch
*
* // Calculate allowances for 10 TiB/month
* const allowances = calculateStorageAllowances(10, pricing)
* console.log(`Rate needed: ${ethers.formatUnits(allowances.rateAllowance, 18)} USDFC/epoch`)
* ```
*
* @param storageTiB - Desired storage capacity in TiB/month
* @param pricePerTiBPerEpoch - Current pricing from storage service
* @returns Calculated allowances for the specified capacity
*/
export declare function calculateStorageAllowances(storageTiB: number, pricePerTiBPerEpoch: bigint): StorageAllowances;
/**
* Calculate actual storage capacity from current allowances
*
* This is the inverse of calculateStorageAllowances - it determines how much
* storage capacity the current allowances support.
*
* @param rateAllowance - Current rate allowance in its smallest unit
* @param pricePerTiBPerEpoch - Current pricing from storage service
* @returns Storage capacity in TiB that can be supported
*/
export declare function calculateActualCapacity(rateAllowance: bigint, pricePerTiBPerEpoch: bigint): number;
/**
* Calculate storage capacity from USDFC amount
*
* Determines how much storage can be purchased with a given USDFC amount,
* accounting for the 30-day lockup period.
*
* @param usdfcAmount - Amount of USDFC in its smallest unit
* @param pricePerTiBPerEpoch - Current pricing from storage service
* @returns Storage capacity in TiB/month
*/
export declare function calculateStorageFromUSDFC(usdfcAmount: bigint, pricePerTiBPerEpoch: bigint): number;
/**
* Compute the additional deposit required to fund current usage for a duration.
*
* The WarmStorage service maintains ~30 days of lockup (lockupUsed) and draws future
* lockups from the available deposit (deposited - lockupUsed). To keep the current
* rails alive for N days, ensure available >= N days of spend at the current rateUsed.
*
* @param status - Current payment status (from getPaymentStatus)
* @param days - Number of days to keep the current usage funded
* @returns Breakdown of required top-up and related values
*/
export declare function computeTopUpForDuration(status: PaymentStatus, days: number): {
topUp: bigint;
available: bigint;
rateUsed: bigint;
perDay: bigint;
lockupUsed: bigint;
};
/**
* Compute the exact adjustment (deposit or withdraw) needed to set runway to `days`.
*
* Positive result indicates a deposit is needed; negative indicates a withdrawal is possible.
*/
export declare function computeAdjustmentForExactDays(status: PaymentStatus, days: number): {
delta: bigint;
targetAvailable: bigint;
available: bigint;
rateUsed: bigint;
perDay: bigint;
lockupUsed: bigint;
};
/**
* Compute the exact adjustment (deposit or withdraw) to reach a target absolute deposit.
*
* Clamps to not withdraw below the currently locked amount.
*/
export declare function computeAdjustmentForExactDeposit(status: PaymentStatus, targetDeposit: bigint): {
delta: bigint;
clampedTarget: bigint;
lockupUsed: bigint;
};
/**
* Compute adjustment needed to maintain target runway AFTER adding a new piece
*
* This function accounts for both:
* - The new piece's lockup requirement
* - The new piece's ongoing per-epoch cost (rate)
*
* @param status - Current payment status
* @param days - Target runway in days
* @param pieceSizeBytes - Size of the piece (CAR, File, etc.) file being uploaded in bytes
* @param pricePerTiBPerEpoch - Current pricing from storage service
* @returns Adjustment details including total delta needed
*/
export declare function computeAdjustmentForExactDaysWithPiece(status: PaymentStatus, days: number, pieceSizeBytes: number, pricePerTiBPerEpoch: bigint): {
delta: bigint;
targetDeposit: bigint;
currentDeposit: bigint;
newLockupUsed: bigint;
newRateUsed: bigint;
};
/**
* Calculate storage capacity from deposit amount
*
* This function calculates how much storage capacity a deposit can support,
* treating WarmStorage as fully trusted with max allowances, i.e. not
* accounting for allowance limits. If usage limits need to be accounted for
* then the capacity can be capped by either deposit or allowances.
* This function accounts for the 30-day lockup requirement.
*
* @param depositAmount - Amount deposited in USDFC
* @param pricePerTiBPerEpoch - Current pricing from storage service
* @returns Storage capacity information
*/
export declare function calculateDepositCapacity(depositAmount: bigint, pricePerTiBPerEpoch: bigint): {
tibPerMonth: number;
gibPerMonth: number;
monthlyPayment: bigint;
requiredLockup: bigint;
totalRequired: bigint;
isDepositSufficient: boolean;
};
/**
* Calculate required allowances from piece size
*
* Simple wrapper that converts piece size to storage allowances.
*
* @param pieceSizeBytes - Size of the piece (CAR, File, etc.) file in bytes
* @param pricePerTiBPerEpoch - Current pricing from storage service
* @returns Required allowances for the piece
*/
export declare function calculateRequiredAllowances(pieceSizeBytes: number, pricePerTiBPerEpoch: bigint): StorageAllowances;
export declare function calculateStorageRunway(status?: Pick<PaymentStatus, 'filecoinPayBalance' | 'currentAllowances'> | null): StorageRunwaySummary;
/**
* Payment capacity validation for a specific file
*/
export interface PaymentCapacityCheck {
canUpload: boolean;
storageTiB: number;
required: StorageAllowances;
issues: {
insufficientDeposit?: bigint;
insufficientRateAllowance?: bigint;
insufficientLockupAllowance?: bigint;
};
suggestions: string[];
}
/**
* Calculate piece upload deposit requirements
*
* @param status - Current payment status
* @param pieceSizeBytes - Size of the piece (CAR, File, etc.) file in bytes
* @param pricePerTiBPerEpoch - Current pricing from storage service
* @returns Piece upload deposit requirements
*/
export declare function calculatePieceUploadRequirements(status: PaymentStatus, pieceSizeBytes: number, pricePerTiBPerEpoch: bigint): {
required: StorageAllowances;
totalDepositNeeded: bigint;
insufficientDeposit: bigint;
canUpload: boolean;
};
/**
* Validate payment capacity for a specific piece size
*
* This function checks if the deposit is sufficient for the piece upload. It
* does not account for allowances since WarmStorage is assumed to be given
* full trust with max allowances.
*
* **Note**: This function will attempt to automatically set max allowances
* unless using session key authentication, in which case allowances must
* be configured separately by the owner wallet.
*
* Example usage:
* ```typescript
* const fileSize = 10 * 1024 * 1024 * 1024 // 10 GiB
* const capacity = await validatePaymentCapacity(synapse, fileSize)
*
* if (!capacity.canUpload) {
* console.error('Cannot upload file with current payment setup')
* capacity.suggestions.forEach(s => console.log(` - ${s}`))
* }
* ```
*
* @param synapse - Initialized Synapse instance
* @param pieceSizeBytes - Size of the piece (CAR, File, etc.) file in bytes
* @returns Capacity check result
*/
export declare function validatePaymentCapacity(synapse: Synapse, pieceSizeBytes: number): Promise<PaymentCapacityCheck>;
//# sourceMappingURL=index.d.ts.map