import { type ValidCreateActionArgs, type ValidListActionsArgs, type ValidListCertificatesArgs, type ValidListOutputsArgs } from '@bsv/sdk/wallet/validationHelpers'; import { AbortActionResult, Beef, InternalizeActionArgs, ListActionsResult, ListOutputsResult, PubKeyHex, ListCertificatesResult, TrustSelf, RelinquishCertificateArgs, RelinquishOutputArgs, AbortActionArgs, WalletLoggerInterface, ChainTracker } from '@bsv/sdk'; import type { SpendVerifierInterface } from '@bsv/sdk'; import { GetReqsAndBeefResult } from './methods/processAction'; import { PostReqsToNetworkResult } from './methods/attemptToPostReqsToNetwork'; import { StorageReaderWriter, StorageReaderWriterOptions } from './StorageReaderWriter'; import { EntityProvenTxReq } from './schema/entities'; import { ServicesCallHistory, WalletServices } from '../sdk/WalletServices.interfaces'; import { AuthId, FindCertificatesArgs, FindOutputBasketsArgs, FindOutputsArgs, FindProvenTxReqsArgs, FindStaleMerkleRootsArgs, ProcessSyncChunkResult, ProvenOrRawTx, PurgeParams, PurgeResults, RequestSyncChunkArgs, StorageCreateActionResult, StorageFeeModel, StorageGetBeefOptions, StorageInternalizeActionResult, StorageProcessActionArgs, StorageProcessActionResults, StoragePrepareNoSendExpiryResult, StorageActivateNoSendExpiryArgs, StorageActivateNoSendExpiryResult, StorageArmNoSendExpiryArgs, StorageProvenOrReq, SyncChunk, TrxToken, UpdateProvenTxReqWithNewProvenTxArgs, UpdateProvenTxReqWithNewProvenTxResult, WalletStorageProvider } from '../sdk/WalletStorage.interfaces'; import { Chain, TransactionStatus } from '../sdk/types'; import { TableProvenTxReq, TableProvenTxReqDynamics } from '../../src/storage/schema/tables/TableProvenTxReq'; import { TableOutputBasket } from '../../src/storage/schema/tables/TableOutputBasket'; import { TableOutput, TableOutputX } from '../../src/storage/schema/tables/TableOutput'; import { TableOutputTag } from '../../src/storage/schema/tables/TableOutputTag'; import { TableTxLabel } from '../../src/storage/schema/tables/TableTxLabel'; import { TableMonitorEvent } from '../../src/storage/schema/tables/TableMonitorEvent'; import { TableUser } from '../../src/storage/schema/tables/TableUser'; import { TableCertificateX } from './schema/tables/TableCertificate'; import { TableProvenTx } from './schema/tables/TableProvenTx'; import { TableActionBatch, TableActionBatchBlob, TableActionBatchOutput } from './schema/tables/TableActionBatch'; import { AbortActionBatchResult, ActionBatchManifest, BeginActionBatchArgs, BeginActionBatchResult, CommitActionBatchByDigestArgs, CommitActionBatchResult, ExtendActionBatchArgs, ExtendActionBatchResult, PrepareActionBatchCommitResult, PutActionBatchBlobArgs, PutActionBatchPackArgs, ResumeActionBatchArgs, ResumeActionBatchResult, RenewActionBatchResult, StorageCapabilities } from '../sdk/ActionBatch.interfaces'; import { ManagedChangeInputCandidate } from './methods/availableManagedChange'; import { ManagedChangePolicy, ManagedChangePolicyOptions } from './methods/managedChangePolicy'; export declare abstract class StorageProvider extends StorageReaderWriter implements WalletStorageProvider { isDirty: boolean; _services?: WalletServices; feeModel: StorageFeeModel; commissionSatoshis: number; commissionPubKeyHex?: PubKeyHex; maxRecursionDepth?: number; readonly actionBatchMaxReservedOutputs: number; readonly managedChangePolicy: ManagedChangePolicy; readonly scriptVerifier?: SpendVerifierInterface; static defaultOptions(): { feeModel: StorageFeeModel; commissionSatoshis: number; commissionPubKeyHex: undefined; actionBatchMaxReservedOutputs: number; managedChangePolicy: ManagedChangePolicy; }; static createStorageBaseOptions(chain: Chain): StorageProviderOptions; constructor(options: StorageProviderOptions); abstract reviewStatus(args: { agedLimit: Date; trx?: TrxToken; }): Promise<{ log: string; }>; abstract purgeData(params: PurgeParams, trx?: TrxToken): Promise; abstract allocateChangeInput(userId: number, basketId: number, targetSatoshis: number, exactSatoshis: number | undefined, excludeSending: boolean, transactionId: number): Promise; /** Mark a planned set of change inputs spent within the caller's transaction. */ markChangeInputsSpent(outputIds: number[], transactionId: number, trx: TrxToken): Promise; /** * Insert outputs that do not need their generated ids returned to the * caller. Engines with a multi-row insert override this common-path helper; * the fallback preserves existing storage implementations unchanged. */ insertOutputs(outputs: TableOutput[], trx?: TrxToken): Promise; /** Return unreserved wallet-managed outputs eligible for automatic funding. */ findAvailableManagedChangeInputs(userId: number, basketId: number, excludeSending: boolean, trx?: TrxToken): Promise; /** Read only the fields needed by the in-memory funding planner. */ findAvailableManagedChangeInputCandidates(userId: number, basketId: number, excludeSending: boolean, trx?: TrxToken): Promise; /** Read the current status of a set of source transactions without loading raw transaction bytes. */ findTransactionStatusesByIds(userId: number, transactionIds: number[], trx?: TrxToken): Promise>; /** * Lock and return the selected funding rows whose source transaction and * action-batch reservation state still permit allocation. */ findFundingOutputsForUpdate(userId: number, outputIds: number[], statuses: TransactionStatus[], trx: TrxToken): Promise>; abstract getProvenOrRawTx(txid: string, trx?: TrxToken): Promise; /** * Resolve several transaction proofs in one storage operation when the * backend supports it. The default preserves compatibility for custom * providers; SQL and IndexedDB providers override this hot path. */ getProvenOrRawTxs(txids: string[], trx?: TrxToken): Promise>; abstract getRawTxOfKnownValidTransaction(txid?: string, offset?: number, length?: number, trx?: TrxToken): Promise; abstract getLabelsForTransactionId(transactionId?: number, trx?: TrxToken): Promise; abstract getTagsForOutputId(outputId: number, trx?: TrxToken): Promise; abstract listActions(auth: AuthId, args: ValidListActionsArgs): Promise; abstract listOutputs(auth: AuthId, args: ValidListOutputsArgs): Promise; abstract countChangeInputs(userId: number, basketId: number, excludeSending: boolean): Promise; insertActionBatch(_batch: TableActionBatch, _trx?: TrxToken): Promise; findActionBatch(_userId: number, _batchId: string, _trx?: TrxToken): Promise; findActionBatchForUpdate(userId: number, batchId: string, trx: TrxToken): Promise; findExpiredActionBatches(_now: Date, _trx?: TrxToken): Promise; updateActionBatch(_actionBatchId: number, _update: Partial, _trx?: TrxToken): Promise; deleteActionBatch(_actionBatchId: number, _trx?: TrxToken): Promise; reserveActionBatchOutputs(_reservations: TableActionBatchOutput[], _trx?: TrxToken): Promise; findActionBatchOutputIds(_actionBatchId: number, _trx?: TrxToken): Promise; findReservedActionBatchOutputIds(_outputIds: number[], _trx?: TrxToken): Promise; deleteActionBatchOutputReservations(_actionBatchId: number, _trx?: TrxToken): Promise; putActionBatchBlobRecord(_blob: TableActionBatchBlob, _trx?: TrxToken): Promise; findActionBatchBlobRecord(_actionBatchId: number, _digest: string, _trx?: TrxToken): Promise; findActionBatchBlobRecords(actionBatchId: number, digests: string[], trx?: TrxToken): Promise; putActionBatchBlobRecords(blobs: TableActionBatchBlob[], trx?: TrxToken): Promise; deleteActionBatchBlobRecords(_actionBatchId: number, _trx?: TrxToken): Promise; getCapabilities(): Promise; /** * Restrict remotely requested proof work to transactions tracked by the * authenticated wallet. ProvenTxReq rows are globally deduplicated, so their * own schema has no userId column and must be authorized through transactions. */ findProvenTxReqsAuth(auth: AuthId, args: FindProvenTxReqsArgs): Promise; prepareNoSendExpiry(auth: AuthId, args: ValidCreateActionArgs): Promise; activateNoSendExpiry(auth: AuthId, args: StorageActivateNoSendExpiryArgs): Promise; armNoSendExpiry(auth: AuthId, args: StorageArmNoSendExpiryArgs): Promise; protected supportsNoSendExpiryPersistence(): boolean; protected supportsActionBatchPersistence(): boolean; /** Custom providers may require physical expiry cleanup before reservations are queried. */ protected requiresActionBatchCleanupBeforeCreateAction(): boolean; beginActionBatch(auth: AuthId, args: BeginActionBatchArgs): Promise; extendActionBatch(auth: AuthId, args: ExtendActionBatchArgs): Promise; renewActionBatch(auth: AuthId, batchId: string): Promise; resumeActionBatch(auth: AuthId, args: ResumeActionBatchArgs): Promise; prepareActionBatchCommit(auth: AuthId, manifest: ActionBatchManifest): Promise; putActionBatchBlob(auth: AuthId, args: PutActionBatchBlobArgs): Promise; putActionBatchPack(auth: AuthId, args: PutActionBatchPackArgs): Promise; commitActionBatch(auth: AuthId, manifest: ActionBatchManifest): Promise; commitActionBatchByDigest(auth: AuthId, args: CommitActionBatchByDigestArgs): Promise; abortActionBatch(auth: AuthId, batchId: string): Promise; findOutputsByIds(outputIds: number[], trx?: TrxToken): Promise>; findStaleMerkleRoots(args: FindStaleMerkleRootsArgs): Promise; findOutputsByOutpoints(userId: number, outpoints: Array<{ txid: string; vout: number; }>, trx?: TrxToken): Promise>; findOutputsByOutpointsForUpdate(userId: number, outpoints: Array<{ txid: string; vout: number; }>, trx: TrxToken, _noScript?: boolean): Promise>; findOrInsertOutputBasketsBulk(userId: number, names: string[], trx?: TrxToken): Promise>; findOrInsertOutputTagsBulk(userId: number, tags: string[], trx?: TrxToken): Promise>; findOrInsertTxLabelsBulk(userId: number, labels: string[], trx?: TrxToken): Promise>; sumSpendableSatoshisInBasket(userId: number, basketId: number, excludeSending: boolean, trx?: TrxToken): Promise; abstract findCertificatesAuth(auth: AuthId, args: FindCertificatesArgs): Promise; abstract findOutputBasketsAuth(auth: AuthId, args: FindOutputBasketsArgs): Promise; abstract findOutputsAuth(auth: AuthId, args: FindOutputsArgs): Promise; abstract insertCertificateAuth(auth: AuthId, certificate: TableCertificateX): Promise; abstract adminStats(adminIdentityKey: string): Promise; recentlyActiveUsers(limit?: number, trx?: TrxToken): Promise; isStorageProvider(): boolean; setServices(v: WalletServices): void; getServices(): WalletServices; private findAbortableTransaction; private observeAbortChainProtection; private invalidateAbortedTransaction; abortAction(auth: AuthId, args: AbortActionArgs): Promise; internalizeAction(auth: AuthId, args: InternalizeActionArgs): Promise; /** * Given an array of transaction txids with current ProvenTxReq ready-to-share status, * lookup their ProvenTxReqApi req records. * For the txids with reqs and status still ready to send construct a single merged beef. * * @param txids * @param knownTxids * @param trx */ getReqsAndBeefToShareWithWorld(txids: string[], knownTxids: string[], trx?: TrxToken): Promise; mergeReqToBeefToShareExternally(req: TableProvenTxReq, mergeToBeef: Beef, knownTxids: string[], trx?: TrxToken): Promise; /** * Checks if txid is a known valid ProvenTx and returns it if found. * Next checks if txid is a current ProvenTxReq and returns that if found. * If `newReq` is provided and an existing ProvenTxReq isn't found, * use `newReq` to create a new ProvenTxReq. * * This is safe "findOrInsert" operation using retry if unique index constraint * is violated by a race condition insert. * * @param txid * @param newReq * @param trx * @returns */ private upsertProvenTxReq; getProvenOrReq(txid: string, newReq?: TableProvenTxReq, trx?: TrxToken): Promise; updateTransactionsStatus(transactionIds: number[], status: TransactionStatus, trx?: TrxToken): Promise; private releaseInputsAllocatedToFailedTransaction; private markFailedTransactionOutputsNotSpendable; private protectNoSendExpiryReclaimInputOnFailure; /** * For all `status` values besides 'failed', just updates the transaction records status property. * * For 'status' of 'failed', attempts to make outputs previously allocated as inputs to this transaction usable again * and makes outputs generated by this transaction non-spendable. * * @param status * @param transactionId * @param userId * @param reference * @param trx */ updateTransactionStatus(status: TransactionStatus, transactionId?: number, userId?: number, reference?: string, trx?: TrxToken): Promise; createAction(auth: AuthId, args: ValidCreateActionArgs): Promise; processAction(auth: AuthId, args: StorageProcessActionArgs): Promise; attemptToPostReqsToNetwork(reqs: EntityProvenTxReq[], trx?: TrxToken, logger?: WalletLoggerInterface): Promise; listCertificates(auth: AuthId, args: ValidListCertificatesArgs): Promise; verifyKnownValidTransaction(txid: string, trx?: TrxToken): Promise; /** * Pulls data from storage to build a valid beef for a txid. * * Optionally merges the data into an existing beef. * Optionally requires a minimum number of proof levels. * * @param txid * @param mergeToBeef * @param trustSelf * @param knownTxids * @param trx * @param requiredLevels * @returns */ getValidBeefForKnownTxid(txid: string, mergeToBeef?: Beef, trustSelf?: TrustSelf, knownTxids?: string[], trx?: TrxToken, requiredLevels?: number): Promise; /** * Handles the proven-tx branch of getValidBeefForTxid. * * Returns the beef if the proof was merged and we can stop, or `undefined` to * signal that the caller should fall through to the rawTx path. May also * populate `r.rawTx` so the rawTx path can proceed without re-fetching. */ private handleProvenTxBranch; getValidBeefForTxid(...[txid, mergeToBeef, trustSelf, knownTxids, trx, requiredLevels, chainTracker, skipInvalidProofs]: [ txid: string, mergeToBeef?: Beef, trustSelf?: TrustSelf, knownTxids?: string[], trx?: TrxToken, requiredLevels?: number, chainTracker?: ChainTracker, skipInvalidProofs?: boolean ]): Promise; getBeefForTransaction(txid: string, options: StorageGetBeefOptions): Promise; getBeefForTransactions(txids: string[], options: StorageGetBeefOptions): Promise; findMonitorEventById(id: number, trx?: TrxToken): Promise; relinquishCertificate(auth: AuthId, args: RelinquishCertificateArgs): Promise; relinquishOutput(auth: AuthId, args: RelinquishOutputArgs): Promise; processSyncChunk(args: RequestSyncChunkArgs, chunk: SyncChunk): Promise; /** * Handles storage changes when a valid MerklePath and mined block header are found for a ProvenTxReq txid. * * Performs the following storage updates (typically): * 1. Lookup the exising `ProvenTxReq` record for its rawTx * 2. Insert a new ProvenTx record using properties from `args` and rawTx, yielding a new provenTxId * 3. Update ProvenTxReq record with status 'completed' and new provenTxId value (and history of status changed) * 4. Unpack notify transactionIds from req and update each transaction's status to 'completed', provenTxId value. * 5. Update ProvenTxReq history again to record that transactions have been notified. * 6. Return results... * * Alterations of "typically" to handle: */ updateProvenTxReqWithNewProvenTx(args: UpdateProvenTxReqWithNewProvenTxArgs, validatedCandidate?: TableProvenTx): Promise; /** Authorize and validate remote proof completion before mutating shared proof state. */ updateProvenTxReqWithNewProvenTxAuth(auth: AuthId, args: UpdateProvenTxReqWithNewProvenTxArgs): Promise; /** * Reconcile completed proof requests whose transaction fan-out previously * failed or whose durable notification state drifted. * * This is called by TaskReviewStatus so a completed request with * `notified = false` is retried and can become eligible for normal purge. */ reconcileCompletedProvenTxReqs(): Promise<{ log: string; }>; private prepareProofRecoveryOutputVerdicts; private restoreProofRecoveryInputs; private restoreProofRecoveryOutputs; private restoreTransactionForProof; /** * Restore every failed local copy of a transaction before proof completion. * Also heals the request's notification set from the authoritative txid * lookup so TaskUnFail cannot omit a local copy after notification drift. */ unfailTransactionsForProof(req: EntityProvenTxReq, indent?: number, requestUpdate?: Pick): Promise; private reconcileProvenTxReqTransactions; /** * For each spendable output in the 'default' basket of the authenticated user, * verify that the output script, satoshis, vout and txid match that of an output * still in the mempool of at least one service provider. * * @returns object with invalidSpendableOutputs array. A good result is an empty array. */ confirmSpendableOutputs(): Promise<{ invalidSpendableOutputs: TableOutput[]; }>; updateProvenTxReqDynamics(id: number, update: Partial, trx?: TrxToken): Promise; extendOutput(o: TableOutput, includeBasket?: boolean, includeTags?: boolean, trx?: TrxToken): Promise; validateOutputScript(o: TableOutput, trx?: TrxToken): Promise; } export interface StorageProviderOptions extends StorageReaderWriterOptions { chain: Chain; feeModel: StorageFeeModel; /** * Transactions created by this Storage can charge a fee per transaction. * A value of zero disables commission fees. */ commissionSatoshis: number; /** * If commissionSatoshis is greater than zero, must be a valid public key hex string. * The actual locking script for each commission will use a public key derived * from this key by information stored in the commissions table. */ commissionPubKeyHex?: PubKeyHex; /** * Optional verifier for server-side action-batch script checks. This Wallet * Toolbox extension leaves the BRC-100 wallet interface unchanged. */ scriptVerifier?: SpendVerifierInterface; /** * Maximum persisted outputs one action-batch workspace may reserve. * Defaults to 256; -1 disables this cumulative provider limit. */ actionBatchMaxReservedOutputs?: number; /** * Optional wallet-managed liquidity tuning. Values are soft shaping and * comparison budgets; none can prevent an otherwise fundable action. Each * limit accepts -1 for an explicit operator-selected unlimited mode. */ managedChangePolicy?: ManagedChangePolicyOptions; } export declare function validateStorageFeeModel(v?: StorageFeeModel): StorageFeeModel; export interface StorageAdminStats { requestedBy: string; when: string; usersDay: number; usersWeek: number; usersMonth: number; usersTotal: number; transactionsDay: number; transactionsWeek: number; transactionsMonth: number; transactionsTotal: number; txCompletedDay: number; txCompletedWeek: number; txCompletedMonth: number; txCompletedTotal: number; txFailedDay: number; txFailedWeek: number; txFailedMonth: number; txFailedTotal: number; txAbandonedDay: number; txAbandonedWeek: number; txAbandonedMonth: number; txAbandonedTotal: number; txUnprocessedDay: number; txUnprocessedWeek: number; txUnprocessedMonth: number; txUnprocessedTotal: number; txSendingDay: number; txSendingWeek: number; txSendingMonth: number; txSendingTotal: number; txUnprovenDay: number; txUnprovenWeek: number; txUnprovenMonth: number; txUnprovenTotal: number; txUnsignedDay: number; txUnsignedWeek: number; txUnsignedMonth: number; txUnsignedTotal: number; txNosendDay: number; txNosendWeek: number; txNosendMonth: number; txNosendTotal: number; txNonfinalDay: number; txNonfinalWeek: number; txNonfinalMonth: number; txNonfinalTotal: number; txUnfailDay: number; txUnfailWeek: number; txUnfailMonth: number; txUnfailTotal: number; satoshisDefaultDay: number; satoshisDefaultWeek: number; satoshisDefaultMonth: number; satoshisDefaultTotal: number; satoshisOtherDay: number; satoshisOtherWeek: number; satoshisOtherMonth: number; satoshisOtherTotal: number; basketsDay: number; basketsWeek: number; basketsMonth: number; basketsTotal: number; labelsDay: number; labelsWeek: number; labelsMonth: number; labelsTotal: number; tagsDay: number; tagsWeek: number; tagsMonth: number; tagsTotal: number; } export interface AdminStatsResult extends StorageAdminStats { servicesStats?: ServicesCallHistory; monitorStats?: ServicesCallHistory; } //# sourceMappingURL=StorageProvider.d.ts.map