diff --git a/index.js b/index.js index 80f0b0d..eb7d94e 100644 --- a/index.js +++ b/index.js @@ -32,6 +32,12 @@ export { export { IWalletAccount } from './src/wallet-account.js' -export { NotImplementedError, SignerError } from './src/errors.js' +export { + NotImplementedError, + SignerError, + UnsupportedOperationError, + ValueError, + NoSuchElementError +} from './src/errors.js' export { ISigner } from './src/signer.js' diff --git a/src/errors.js b/src/errors.js index 8154485..42beff1 100644 --- a/src/errors.js +++ b/src/errors.js @@ -38,3 +38,44 @@ export class SignerError extends Error { this.name = 'SignerError' } } + +export class UnsupportedOperationError extends Error { + /** + * Create a new unsupported operation error. Thrown by an optional operation + * that the concrete implementation deliberately does not support. + * + * @param {string} operation - The name of the operation that is not supported. + */ + constructor (operation) { + super(`Operation '${operation}' is not supported by this protocol.`) + + this.name = 'UnsupportedOperationError' + } +} + +export class ValueError extends Error { + /** + * Create a new value error. Thrown when an argument fails validation. + * + * @param {string} message - The error's message. + */ + constructor (message) { + super(message) + + this.name = 'ValueError' + } +} + +export class NoSuchElementError extends Error { + /** + * Create a new no such element error. Thrown when a lookup finds no element for + * the given identifier. + * + * @param {string} message - The error's message. + */ + constructor (message) { + super(message) + + this.name = 'NoSuchElementError' + } +} diff --git a/src/protocols/index.js b/src/protocols/index.js index 4ca8ff6..937a9d3 100644 --- a/src/protocols/index.js +++ b/src/protocols/index.js @@ -68,6 +68,25 @@ /** @typedef {import('./swidge-protocol.js').SwidgeSupportedToken} SwidgeSupportedToken */ /** @typedef {import('./swidge-protocol.js').SwidgeSupportedTokensOptions} SwidgeSupportedTokensOptions */ +/** @typedef {import('./sda-protocol.js').Blockchain} Blockchain */ +/** @typedef {import('./sda-protocol.js').SdaToken} SdaToken */ +/** @typedef {import('./sda-protocol.js').SdaDepositAddressLimits} SdaDepositAddressLimits */ +/** @typedef {import('./sda-protocol.js').SdaRoutesOptions} SdaRoutesOptions */ +/** @typedef {import('./sda-protocol.js').SdaRoute} SdaRoute */ +/** @typedef {import('./sda-protocol.js').SdaDepositOptions} SdaDepositOptions */ +/** @typedef {import('./sda-protocol.js').SdaFeeType} SdaFeeType */ +/** @typedef {import('./sda-protocol.js').SdaFee} SdaFee */ +/** @typedef {import('./sda-protocol.js').SdaDepositQuote} SdaDepositQuote */ +/** @typedef {import('./sda-protocol.js').SdaCreateDepositAddressOptions} SdaCreateDepositAddressOptions */ +/** @typedef {import('./sda-protocol.js').SdaDepositAddress} SdaDepositAddress */ +/** @typedef {import('./sda-protocol.js').SdaTransferStatus} SdaTransferStatus */ +/** @typedef {import('./sda-protocol.js').SdaTransfer} SdaTransfer */ +/** @typedef {import('./sda-protocol.js').SdaTransfersOptions} SdaTransfersOptions */ +/** @typedef {import('./sda-protocol.js').SdaRecoverById} SdaRecoverById */ +/** @typedef {import('./sda-protocol.js').SdaRecoverByAddress} SdaRecoverByAddress */ +/** @typedef {import('./sda-protocol.js').SdaRecoveryOptions} SdaRecoveryOptions */ +/** @typedef {import('./sda-protocol.js').SdaRecoveryResult} SdaRecoveryResult */ + export { default as SwapProtocol, ISwapProtocol } from './swap-protocol.js' export { default as BridgeProtocol, IBridgeProtocol } from './bridge-protocol.js' @@ -77,3 +96,5 @@ export { default as LendingProtocol, ILendingProtocol } from './lending-protocol export { default as FiatProtocol, IFiatProtocol } from './fiat-protocol.js' export { default as SwidgeProtocol, ISwidgeProtocol } from './swidge-protocol.js' + +export { default as SdaProtocol, ISdaProtocol } from './sda-protocol.js' diff --git a/src/protocols/sda-protocol.js b/src/protocols/sda-protocol.js new file mode 100644 index 0000000..d6cf997 --- /dev/null +++ b/src/protocols/sda-protocol.js @@ -0,0 +1,556 @@ +// Copyright 2024 Tether Operations Limited +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +'use strict' + +import { NotImplementedError, UnsupportedOperationError } from '../errors.js' + +/** @typedef {import('../wallet-account-read-only.js').IWalletAccountReadOnly} IWalletAccountReadOnly */ + +/** @typedef {import('../wallet-account.js').IWalletAccount} IWalletAccount */ + +/** @typedef {import('../errors.js').ValueError} ValueError */ + +/** @typedef {import('../errors.js').NoSuchElementError} NoSuchElementError */ + +/** + * A blockchain identifier: a numeric chain id (e.g. `1`) or a protocol-specific chain name (e.g. `'ethereum'`). + * + * @typedef {string | number} Blockchain + */ + +/** + * A normalized token reference. `token` is the identifier the protocol expects in SDA calls; `address` is the + * on-chain contract address when applicable (absent for native gas tokens). + * + * @typedef {Object} SdaToken + * @property {string} token - The protocol-specific token identifier to use in SDA calls. + * @property {Blockchain} chain - The chain on which the token lives. + * @property {string} symbol - The token symbol (e.g., 'USDC', 'USDT'). + * @property {number} decimals - The number of decimal places for the token's base unit. + * @property {string} [address] - The token contract address, if applicable. + * @property {string} [name] - The token's full name. + */ + +/** + * Per-route deposit limits, denominated in the base unit of the route's input token. Either bound may be absent + * when the protocol does not enforce it; a protocol that only enforces limits in another denomination (e.g. USD) + * omits `limits` rather than converting. + * + * @typedef {Object} SdaDepositAddressLimits + * @property {number | bigint} [min] - Minimum deposit amount, in the input token's base unit. + * @property {number | bigint} [max] - Maximum deposit amount, in the input token's base unit. + */ + +/** + * Optional filters for narrowing route discovery. + * + * @typedef {Object} SdaRoutesOptions + * @property {Blockchain} [sourceChain] - Restrict to routes that accept deposits from this chain. + * @property {string} [sourceToken] - Restrict to routes that accept this input token. + * @property {Blockchain} [destinationChain] - Restrict to routes that deliver to this chain. + * @property {string} [outputAsset] - Restrict to routes that deliver this asset. + */ + +/** + * A supported conversion route: one or more source chains and their accepted input tokens, the destination chain, + * and the asset delivered there. + * + * @typedef {Object} SdaRoute + * @property {Blockchain[]} sourceChains - The source chains this route accepts deposits from. A list because some + * protocols issue one address valid across a VM family. + * @property {SdaToken[]} inputTokens - The deposit tokens accepted on the source side. + * @property {Blockchain} destinationChain - The chain the converted asset is delivered to. + * @property {SdaToken} [outputAsset] - The asset delivered to the destination (e.g., USDT). If unset, the route + * delivers each input token as its own equivalent on the destination chain. + * @property {SdaDepositAddressLimits} [limits] - Deposit limits for this route. + * @property {boolean} [reusable] - Whether addresses issued for this route can receive more than one deposit. + * @property {number} [estimatedDuration] - Typical end-to-end duration in seconds. + */ + +/** + * Options for fetching a deposit quote — a non-binding estimate of what a given deposit would deliver. + * + * @typedef {Object} SdaDepositOptions + * @property {Blockchain} sourceChain - The chain the deposit originates from. + * @property {string} inputToken - The protocol identifier of the token being deposited. + * @property {Blockchain} destinationChain - The chain the converted asset is delivered to. + * @property {string} [outputAsset] - The protocol identifier of the asset to deliver. Omit for protocols that deliver + * each input token as its own equivalent. + * @property {number | bigint} inputAmount - The amount to deposit, in the input token's base unit. + */ + +/** + * The category of a fee charged by the protocol. + * + * @typedef {'network' | 'protocol' | 'affiliate' | 'other'} SdaFeeType + */ + +/** + * A single itemised fee. + * + * @typedef {Object} SdaFee + * @property {SdaFeeType} type - The category of the fee. + * @property {bigint} amount - The fee amount, in the fee token's base unit. + * @property {string} token - The token in which the fee is denominated. + * @property {Blockchain} [chain] - The chain on which the fee is charged. + * @property {boolean} [included] - Whether the fee is already reflected in the quoted output amount. + * @property {string} [description] - A human-readable description of the fee. + */ + +/** + * A non-binding estimate of the asset delivered for a given deposit. + * + * @typedef {Object} SdaDepositQuote + * @property {Blockchain} inputChain - The chain the deposit originates from. + * @property {string} inputToken - The protocol identifier of the deposited token. + * @property {bigint} inputAmount - The amount deposited, in the input token's base unit. + * @property {Blockchain} destinationChain - The chain the converted asset is delivered to. + * @property {string} outputAsset - The protocol identifier of the delivered asset. + * @property {bigint} outputAmount - The estimated amount delivered, in the destination asset's base unit. + * @property {SdaFee[]} fees - Itemised fee breakdown. + * @property {string} [rate] - The effective conversion rate as a string, to avoid precision loss. + * @property {number} [expiry] - Unix timestamp (seconds) at which the quote expires. + * @property {string} [id] - The protocol quote identifier, if the protocol issues one. + */ + +/** + * Options for creating a deposit address. + * + * @typedef {Object} SdaCreateDepositAddressOptions + * @property {Blockchain[]} sourceChains - One or more source chains the address should accept deposits from. Protocols + * that issue one address per VM family use the full list; single-chain protocols use a one-element list. + * @property {Blockchain} destinationChain - The chain the converted asset is delivered to. + * @property {string} [outputAsset] - The protocol identifier of the asset to deliver (e.g., USDT). Omit for protocols + * that deliver each input token as its own equivalent. + * @property {string} [destinationAddress] - The address that receives the delivered asset. Defaults to the bound + * account's address. + */ + +/** + * A deposit address plus its normalized descriptor: where it accepts deposits from, what it accepts, where it + * delivers, and its lifecycle metadata. + * + * @typedef {Object} SdaDepositAddress + * @property {string} address - The deposit address the user sends funds to. + * @property {string} id - The protocol identifier for this SDA, used for status, recovery and disabling. + * @property {Blockchain[]} sourceChains - The chains this address accepts deposits from. + * @property {SdaToken[]} supportedInputTokens - The tokens this address accepts. + * @property {Blockchain} destinationChain - The chain the converted asset is delivered to. + * @property {SdaToken} [outputAsset] - The asset delivered to the destination. If unset, the address delivers each + * input token as its own equivalent on the destination chain. + * @property {string} destinationAddress - The resolved address that receives the delivered asset. + * @property {SdaDepositAddressLimits} [limits] - Deposit limits for this address. + * @property {boolean} reusable - Whether the address can receive more than one deposit. + * @property {number} [expiry] - Unix timestamp (seconds) at which the address's activation expires, when the protocol's + * address activation is time-limited. + */ + +/** + * The lifecycle status of a deposit/transfer through an SDA. + * + * @typedef {'pending' | 'detected' | 'processing' | 'completed' | 'failed' + * | 'refund-pending' | 'refunded' | 'expired'} SdaTransferStatus + */ + +/** + * A single deposit observed at, and processed through, an SDA. + * + * @typedef {Object} SdaTransfer + * @property {string} id - The protocol identifier for this transfer. + * @property {SdaTransferStatus} status - The current status of the transfer. + */ + +/** + * Optional pagination/filtering for transfer history. + * + * @typedef {Object} SdaTransfersOptions + * @property {Blockchain} [sourceChain] - The source chain of the deposit address, required by protocols that key + * addresses by (address, chain). + * @property {number} [limit] - The maximum number of transfers to return. + * @property {number} [skip] - The number of transfers to skip, for offset-based pagination. + * @property {SdaTransferStatus} [status] - Restrict to transfers in this status. + */ + +/** + * Recover a deposit by the SDA identifier. + * + * @typedef {Object} SdaRecoverById + * @property {string} id - The protocol SDA identifier (the `SdaDepositAddress.id`). + */ + +/** + * Recover a deposit by its deposit address. + * + * @typedef {Object} SdaRecoverByAddress + * @property {string} address - The deposit address to reindex. + * @property {Blockchain} [sourceChain] - The chain of the deposit address, required by protocols that key addresses by + * (address, chain). + */ + +/** + * Options for re-processing a deposit that was not picked up automatically (`reindex`). A caller identifies the + * deposit either by SDA id or by its deposit address. + * + * @typedef {SdaRecoverById | SdaRecoverByAddress} SdaRecoveryOptions + */ + +/** + * The outcome of a recovery attempt. + * + * @typedef {Object} SdaRecoveryResult + * @property {'reindexed' | 'pending' | 'failed'} status - The result of the reindex attempt. + * @property {string} [address] - The address that was reindexed. + * @property {string} [id] - The protocol SDA identifier. + * @property {SdaTransfer} [transfer] - The transfer that was recovered, if one resulted. + * @property {string} [message] - A human-readable description of the outcome. + */ + +/** + * Interface for "Smart Deposit Address" (SDA) protocols: services that issue a deposit address, accept a + * stablecoin (or native token) from a supported source chain, convert it, and deliver a chosen asset (e.g., USDT) + * to a chosen destination chain and address. + * + * The required core every protocol implements is route discovery and address creation; every other operation is + * optional. + * + * @interface + */ +export class ISdaProtocol { + /** + * Lists the conversion routes the protocol supports: source chains, accepted input tokens, output assets and + * per-route deposit limits. A protocol that discovers routes by blockchain pairs might require the `sourceChain` + * and `destinationChain` options to be set. + * + * @param {SdaRoutesOptions} [options] - Optional filters for route discovery. + * @returns {Promise} The supported routes. + * @throws {ValueError} If the protocol discovers routes by blockchain pairs and the source or destination blockchain + * is not set. + */ + async getSupportedRoutes (options) { + throw new NotImplementedError('getSupportedRoutes(options)') + } + + /** + * Fetches a non-binding quote (estimate) for a deposit — what a given deposit would deliver. + * + * @param {SdaDepositOptions} options - The quote options. + * @returns {Promise} The quoted deposit details. + * @throws {UnsupportedOperationError} If the protocol does not support this operation. + * @throws {ValueError} If the protocol requires an output asset and none is provided. + */ + async quoteDeposit (options) { + throw new NotImplementedError('quoteDeposit(options)') + } + + /** + * Creates deposit addresses for the given route and destination, ready to receive per the protocol's activation + * lifecycle — a protocol that activates addresses also activates the created address so it is monitored. Returns + * one entry per distinct address: a protocol that issues a single address across a chain family returns one entry + * covering all of `sourceChains`, while a protocol that issues one address per source chain returns one entry each. + * + * @param {SdaCreateDepositAddressOptions} options - The address creation options. + * @returns {Promise} The created deposit addresses, one per distinct address. + * @throws {ValueError} If `destinationAddress` is omitted and no account was bound at construction. + * @throws {ValueError} If the protocol requires an output asset and none is provided. + */ + async createDepositAddress (options) { + throw new NotImplementedError('createDepositAddress(options)') + } + + /** + * Derives a deposit address client-side, without any protocol call and without activating or monitoring it — + * used to verify (derive + compare) or recover an address for a self-custodial protocol. + * + * @param {SdaCreateDepositAddressOptions} options - The same options passed to + * {@link ISdaProtocol#createDepositAddress}; a protocol needing extra derivation inputs declares them on its own + * options type (which extends `SdaCreateDepositAddressOptions`). + * @returns {Promise} The derived deposit address. + * @throws {UnsupportedOperationError} If the protocol does not support this operation. + * @throws {ValueError} If `destinationAddress` is omitted and no account was bound at construction. + */ + async deriveDepositAddress (options) { + throw new NotImplementedError('deriveDepositAddress(options)') + } + + /** + * Looks up an existing deposit address by its identifier — the `SdaDepositAddress.id` returned by + * {@link ISdaProtocol#createDepositAddress}, which round-trips any chain context the protocol needs. + * + * @param {string} id - The deposit-address identifier returned in `SdaDepositAddress.id` (round-trips any chain + * context the protocol needs). + * @returns {Promise} The deposit address descriptor. + * @throws {UnsupportedOperationError} If the protocol does not support this operation. + * @throws {NoSuchElementError} If no such address exists. + */ + async getDepositAddress (id) { + throw new NotImplementedError('getDepositAddress(id)') + } + + /** + * Refreshes the activation of a deposit address so the protocol keeps monitoring it. + * + * @param {string} id - The deposit-address identifier returned in `SdaDepositAddress.id`. + * @returns {Promise} The refreshed deposit address descriptor (with the new `expiry`). + * @throws {UnsupportedOperationError} If the protocol does not support this operation. + */ + async renewDepositAddress (id) { + throw new NotImplementedError('renewDepositAddress(id)') + } + + /** + * Lists the deposits observed at a deposit address. + * + * @param {string} address - The deposit address to list transfers for. + * @param {SdaTransfersOptions} [options] - Optional pagination/filtering, plus `sourceChain` for protocols that key + * addresses by (address, chain). + * @returns {Promise} The transfers for the address. + * @throws {UnsupportedOperationError} If the protocol does not support this operation. + */ + async getTransfers (address, options) { + throw new NotImplementedError('getTransfers(address, options)') + } + + /** + * Lists transfers aggregated by recipient — every deposit routed to the given recipient across all of that + * recipient's deposit addresses and source chains. + * + * @param {Blockchain} destinationChain - The destination chain the transfers are delivered to. + * @param {string} recipient - The recipient (destination) address to aggregate transfers for. + * @param {SdaTransfersOptions} [options] - Optional pagination/filtering. + * @returns {Promise} The transfers routed to the recipient. + * @throws {UnsupportedOperationError} If the protocol does not support this operation. + */ + async getTransfersByRecipient (destinationChain, recipient, options) { + throw new NotImplementedError('getTransfersByRecipient(destinationChain, recipient, options)') + } + + /** + * Retrieves a single transfer by its identifier. + * + * @param {string} id - The transfer identifier. + * @returns {Promise} The transfer's current status. + * @throws {UnsupportedOperationError} If the protocol does not support this operation. + * @throws {NoSuchElementError} If no such transfer exists. + */ + async getTransfer (id) { + throw new NotImplementedError('getTransfer(id)') + } + + /** + * Recovers a deposit or address that was not picked up automatically, using the protocol's recovery mode. + * + * @param {SdaRecoveryOptions} options - The recovery options. + * @returns {Promise} The recovery outcome. + * @throws {UnsupportedOperationError} If the protocol does not support this operation. + */ + async recoverDepositAddress (options) { + throw new NotImplementedError('recoverDepositAddress(options)') + } + + /** + * Disables a deposit address so it no longer accepts deposits. + * + * @param {string} id - The deposit-address identifier returned in `SdaDepositAddress.id` (round-trips any chain + * context the protocol needs). + * @returns {Promise} Resolves once the address has been disabled. + * @throws {UnsupportedOperationError} If the protocol does not support this operation. + */ + async disableDepositAddress (id) { + throw new NotImplementedError('disableDepositAddress(id)') + } +} + +/** + * Abstract base class for "Smart Deposit Address" (SDA) protocols. + * + * @abstract + * @implements {ISdaProtocol} + */ +export default class SdaProtocol { + /** + * Creates a new SDA protocol without binding it to a wallet account. + * + * @overload + * @param {undefined} [account] - The wallet account to use to interact with the protocol. + */ + + /** + * Creates a new read-only SDA protocol. + * + * @overload + * @param {IWalletAccountReadOnly} account - The wallet account to use to interact with the protocol. + */ + + /** + * Creates a new SDA protocol. + * + * @overload + * @param {IWalletAccount} account - The wallet account to use to interact with the protocol. + */ + constructor (account) { + /** + * The wallet account to use to interact with the protocol. The account's address is the default delivery + * destination for created addresses. + * + * @protected + * @type {IWalletAccountReadOnly | IWalletAccount | undefined} + */ + this._account = account + } + + /** + * Lists the conversion routes the protocol supports: source chains, accepted input tokens, output assets and + * per-route deposit limits. A protocol that discovers routes by blockchain pairs might require the `sourceChain` + * and `destinationChain` options to be set. + * + * @abstract + * @param {SdaRoutesOptions} [options] - Optional filters for route discovery. + * @returns {Promise} The supported routes. + * @throws {ValueError} If the protocol discovers routes by blockchain pairs and the source or destination blockchain + * is not set. + */ + async getSupportedRoutes (options) { + throw new NotImplementedError('getSupportedRoutes(options)') + } + + /** + * Fetches a non-binding quote (estimate) for a deposit — what a given deposit would deliver. + * + * @param {SdaDepositOptions} options - The quote options. + * @returns {Promise} The quoted deposit details. + * @throws {UnsupportedOperationError} If the protocol does not support this operation. + * @throws {ValueError} If the protocol requires an output asset and none is provided. + */ + async quoteDeposit (options) { + throw new UnsupportedOperationError('quoteDeposit(options)') + } + + /** + * Creates deposit addresses for the given route and destination, ready to receive per the protocol's activation + * lifecycle — a protocol that activates addresses also activates the created address so it is monitored. Returns + * one entry per distinct address: a protocol that issues a single address across a chain family returns one entry + * covering all of `sourceChains`, while a protocol that issues one address per source chain returns one entry each. + * + * @abstract + * @param {SdaCreateDepositAddressOptions} options - The address creation options. + * @returns {Promise} The created deposit addresses, one per distinct address. + * @throws {ValueError} If `destinationAddress` is omitted and no account was bound at construction. + * @throws {ValueError} If the protocol requires an output asset and none is provided. + */ + async createDepositAddress (options) { + throw new NotImplementedError('createDepositAddress(options)') + } + + /** + * Derives a deposit address client-side, without any protocol call and without activating or monitoring it — + * used to verify (derive + compare) or recover an address for a self-custodial protocol. + * + * @param {SdaCreateDepositAddressOptions} options - The same options passed to + * {@link ISdaProtocol#createDepositAddress}; a protocol needing extra derivation inputs declares them on its own + * options type (which extends `SdaCreateDepositAddressOptions`). + * @returns {Promise} The derived deposit address. + * @throws {UnsupportedOperationError} If the protocol does not support this operation. + * @throws {ValueError} If `destinationAddress` is omitted and no account was bound at construction. + */ + async deriveDepositAddress (options) { + throw new UnsupportedOperationError('deriveDepositAddress(options)') + } + + /** + * Looks up an existing deposit address by its identifier — the `SdaDepositAddress.id` returned by + * {@link ISdaProtocol#createDepositAddress}, which round-trips any chain context the protocol needs. + * + * @param {string} id - The deposit-address identifier returned in `SdaDepositAddress.id` (round-trips any chain + * context the protocol needs). + * @returns {Promise} The deposit address descriptor. + * @throws {UnsupportedOperationError} If the protocol does not support this operation. + * @throws {NoSuchElementError} If no such address exists. + */ + async getDepositAddress (id) { + throw new UnsupportedOperationError('getDepositAddress(id)') + } + + /** + * Refreshes the activation of a deposit address so the protocol keeps monitoring it. + * + * @param {string} id - The deposit-address identifier returned in `SdaDepositAddress.id`. + * @returns {Promise} The refreshed deposit address descriptor (with the new `expiry`). + * @throws {UnsupportedOperationError} If the protocol does not support this operation. + */ + async renewDepositAddress (id) { + throw new UnsupportedOperationError('renewDepositAddress(id)') + } + + /** + * Lists the deposits observed at a deposit address. + * + * @param {string} address - The deposit address to list transfers for. + * @param {SdaTransfersOptions} [options] - Optional pagination/filtering, plus `sourceChain` for protocols that key + * addresses by (address, chain). + * @returns {Promise} The transfers for the address. + * @throws {UnsupportedOperationError} If the protocol does not support this operation. + */ + async getTransfers (address, options) { + throw new UnsupportedOperationError('getTransfers(address, options)') + } + + /** + * Lists transfers aggregated by recipient — every deposit routed to the given recipient across all of that + * recipient's deposit addresses and source chains. + * + * @param {Blockchain} destinationChain - The destination chain the transfers are delivered to. + * @param {string} recipient - The recipient (destination) address to aggregate transfers for. + * @param {SdaTransfersOptions} [options] - Optional pagination/filtering. + * @returns {Promise} The transfers routed to the recipient. + * @throws {UnsupportedOperationError} If the protocol does not support this operation. + */ + async getTransfersByRecipient (destinationChain, recipient, options) { + throw new UnsupportedOperationError('getTransfersByRecipient(destinationChain, recipient, options)') + } + + /** + * Retrieves a single transfer by its identifier. + * + * @param {string} id - The transfer identifier. + * @returns {Promise} The transfer's current status. + * @throws {UnsupportedOperationError} If the protocol does not support this operation. + * @throws {NoSuchElementError} If no such transfer exists. + */ + async getTransfer (id) { + throw new UnsupportedOperationError('getTransfer(id)') + } + + /** + * Recovers a deposit or address that was not picked up automatically, using the protocol's recovery mode. + * + * @param {SdaRecoveryOptions} options - The recovery options. + * @returns {Promise} The recovery outcome. + * @throws {UnsupportedOperationError} If the protocol does not support this operation. + */ + async recoverDepositAddress (options) { + throw new UnsupportedOperationError('recoverDepositAddress(options)') + } + + /** + * Disables a deposit address so it no longer accepts deposits. + * + * @param {string} id - The deposit-address identifier returned in `SdaDepositAddress.id` (round-trips any chain + * context the protocol needs). + * @returns {Promise} Resolves once the address has been disabled. + * @throws {UnsupportedOperationError} If the protocol does not support this operation. + */ + async disableDepositAddress (id) { + throw new UnsupportedOperationError('disableDepositAddress(id)') + } +} diff --git a/types/index.d.ts b/types/index.d.ts index 8f5f271..6e67e92 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -1,3 +1,6 @@ +export { default } from "./src/wallet-manager.js"; +export { IWalletAccount } from "./src/wallet-account.js"; +export { ISigner } from "./src/signer.js"; export type FeeRates = import("./src/wallet-manager.js").FeeRates; export type WalletConfig = import("./src/wallet-manager.js").WalletConfig; export type Transaction = import("./src/wallet-account-read-only.js").Transaction; @@ -5,8 +8,5 @@ export type TransactionResult = import("./src/wallet-account-read-only.js").Tran export type TransferOptions = import("./src/wallet-account-read-only.js").TransferOptions; export type TransferResult = import("./src/wallet-account-read-only.js").TransferResult; export type KeyPair = import("./src/wallet-account.js").KeyPair; -export { default } from "./src/wallet-manager.js"; export { default as WalletAccountReadOnly, IWalletAccountReadOnly } from "./src/wallet-account-read-only.js"; -export { IWalletAccount } from "./src/wallet-account.js"; -export { NotImplementedError, SignerError } from "./src/errors.js"; -export { ISigner } from "./src/signer.js"; +export { NotImplementedError, SignerError, UnsupportedOperationError, ValueError, NoSuchElementError } from "./src/errors.js"; diff --git a/types/src/errors.d.ts b/types/src/errors.d.ts index a6ab66e..f759bf8 100644 --- a/types/src/errors.d.ts +++ b/types/src/errors.d.ts @@ -14,3 +14,29 @@ export class SignerError extends Error { */ constructor(message: string); } +export class UnsupportedOperationError extends Error { + /** + * Create a new unsupported operation error. Thrown by an optional operation + * that the concrete implementation deliberately does not support. + * + * @param {string} operation - The name of the operation that is not supported. + */ + constructor(operation: string); +} +export class ValueError extends Error { + /** + * Create a new value error. Thrown when an argument fails validation. + * + * @param {string} message - The error's message. + */ + constructor(message: string); +} +export class NoSuchElementError extends Error { + /** + * Create a new no such element error. Thrown when a lookup finds no element for + * the given identifier. + * + * @param {string} message - The error's message. + */ + constructor(message: string); +} diff --git a/types/src/protocols/index.d.ts b/types/src/protocols/index.d.ts index e8647b3..bd726a4 100644 --- a/types/src/protocols/index.d.ts +++ b/types/src/protocols/index.d.ts @@ -44,8 +44,27 @@ export type SwidgeStatusResult = import("./swidge-protocol.js").SwidgeStatusResu export type SwidgeSupportedChain = import("./swidge-protocol.js").SwidgeSupportedChain; export type SwidgeSupportedToken = import("./swidge-protocol.js").SwidgeSupportedToken; export type SwidgeSupportedTokensOptions = import("./swidge-protocol.js").SwidgeSupportedTokensOptions; +export type Blockchain = import("./sda-protocol.js").Blockchain; +export type SdaToken = import("./sda-protocol.js").SdaToken; +export type SdaDepositAddressLimits = import("./sda-protocol.js").SdaDepositAddressLimits; +export type SdaRoutesOptions = import("./sda-protocol.js").SdaRoutesOptions; +export type SdaRoute = import("./sda-protocol.js").SdaRoute; +export type SdaDepositOptions = import("./sda-protocol.js").SdaDepositOptions; +export type SdaFeeType = import("./sda-protocol.js").SdaFeeType; +export type SdaFee = import("./sda-protocol.js").SdaFee; +export type SdaDepositQuote = import("./sda-protocol.js").SdaDepositQuote; +export type SdaCreateDepositAddressOptions = import("./sda-protocol.js").SdaCreateDepositAddressOptions; +export type SdaDepositAddress = import("./sda-protocol.js").SdaDepositAddress; +export type SdaTransferStatus = import("./sda-protocol.js").SdaTransferStatus; +export type SdaTransfer = import("./sda-protocol.js").SdaTransfer; +export type SdaTransfersOptions = import("./sda-protocol.js").SdaTransfersOptions; +export type SdaRecoverById = import("./sda-protocol.js").SdaRecoverById; +export type SdaRecoverByAddress = import("./sda-protocol.js").SdaRecoverByAddress; +export type SdaRecoveryOptions = import("./sda-protocol.js").SdaRecoveryOptions; +export type SdaRecoveryResult = import("./sda-protocol.js").SdaRecoveryResult; export { default as SwapProtocol, ISwapProtocol } from "./swap-protocol.js"; export { default as BridgeProtocol, IBridgeProtocol } from "./bridge-protocol.js"; export { default as LendingProtocol, ILendingProtocol } from "./lending-protocol.js"; export { default as FiatProtocol, IFiatProtocol } from "./fiat-protocol.js"; export { default as SwidgeProtocol, ISwidgeProtocol } from "./swidge-protocol.js"; +export { default as SdaProtocol, ISdaProtocol } from "./sda-protocol.js"; diff --git a/types/src/protocols/sda-protocol.d.ts b/types/src/protocols/sda-protocol.d.ts new file mode 100644 index 0000000..144c97d --- /dev/null +++ b/types/src/protocols/sda-protocol.d.ts @@ -0,0 +1,640 @@ +/** @interface */ +export interface ISdaProtocol { + /** + * Lists the conversion routes the protocol supports: source chains, accepted input tokens, output assets and + * per-route deposit limits. A protocol that discovers routes by blockchain pairs might require the `sourceChain` + * and `destinationChain` options to be set. + * + * @param {SdaRoutesOptions} [options] - Optional filters for route discovery. + * @returns {Promise} The supported routes. + * @throws {ValueError} If the protocol discovers routes by blockchain pairs and the source or destination blockchain + * is not set. + */ + getSupportedRoutes(options?: SdaRoutesOptions): Promise; + /** + * Fetches a non-binding quote (estimate) for a deposit — what a given deposit would deliver. + * + * @param {SdaDepositOptions} options - The quote options. + * @returns {Promise} The quoted deposit details. + * @throws {UnsupportedOperationError} If the protocol does not support this operation. + * @throws {ValueError} If the protocol requires an output asset and none is provided. + */ + quoteDeposit(options: SdaDepositOptions): Promise; + /** + * Creates deposit addresses for the given route and destination, ready to receive per the protocol's activation + * lifecycle — a protocol that activates addresses also activates the created address so it is monitored. Returns + * one entry per distinct address: a protocol that issues a single address across a chain family returns one entry + * covering all of `sourceChains`, while a protocol that issues one address per source chain returns one entry each. + * + * @param {SdaCreateDepositAddressOptions} options - The address creation options. + * @returns {Promise} The created deposit addresses, one per distinct address. + * @throws {ValueError} If `destinationAddress` is omitted and no account was bound at construction. + * @throws {ValueError} If the protocol requires an output asset and none is provided. + */ + createDepositAddress(options: SdaCreateDepositAddressOptions): Promise; + /** + * Derives a deposit address client-side, without any protocol call and without activating or monitoring it — + * used to verify (derive + compare) or recover an address for a self-custodial protocol. + * + * @param {SdaCreateDepositAddressOptions} options - The same options passed to + * {@link ISdaProtocol#createDepositAddress}; a protocol needing extra derivation inputs declares them on its own + * options type (which extends `SdaCreateDepositAddressOptions`). + * @returns {Promise} The derived deposit address. + * @throws {UnsupportedOperationError} If the protocol does not support this operation. + * @throws {ValueError} If `destinationAddress` is omitted and no account was bound at construction. + */ + deriveDepositAddress(options: SdaCreateDepositAddressOptions): Promise; + /** + * Looks up an existing deposit address by its identifier — the `SdaDepositAddress.id` returned by + * {@link ISdaProtocol#createDepositAddress}, which round-trips any chain context the protocol needs. + * + * @param {string} id - The deposit-address identifier returned in `SdaDepositAddress.id` (round-trips any chain + * context the protocol needs). + * @returns {Promise} The deposit address descriptor. + * @throws {UnsupportedOperationError} If the protocol does not support this operation. + * @throws {NoSuchElementError} If no such address exists. + */ + getDepositAddress(id: string): Promise; + /** + * Refreshes the activation of a deposit address so the protocol keeps monitoring it. + * + * @param {string} id - The deposit-address identifier returned in `SdaDepositAddress.id`. + * @returns {Promise} The refreshed deposit address descriptor (with the new `expiry`). + * @throws {UnsupportedOperationError} If the protocol does not support this operation. + */ + renewDepositAddress(id: string): Promise; + /** + * Lists the deposits observed at a deposit address. + * + * @param {string} address - The deposit address to list transfers for. + * @param {SdaTransfersOptions} [options] - Optional pagination/filtering, plus `sourceChain` for protocols that key + * addresses by (address, chain). + * @returns {Promise} The transfers for the address. + * @throws {UnsupportedOperationError} If the protocol does not support this operation. + */ + getTransfers(address: string, options?: SdaTransfersOptions): Promise; + /** + * Lists transfers aggregated by recipient — every deposit routed to the given recipient across all of that + * recipient's deposit addresses and source chains. + * + * @param {Blockchain} destinationChain - The destination chain the transfers are delivered to. + * @param {string} recipient - The recipient (destination) address to aggregate transfers for. + * @param {SdaTransfersOptions} [options] - Optional pagination/filtering. + * @returns {Promise} The transfers routed to the recipient. + * @throws {UnsupportedOperationError} If the protocol does not support this operation. + */ + getTransfersByRecipient(destinationChain: Blockchain, recipient: string, options?: SdaTransfersOptions): Promise; + /** + * Retrieves a single transfer by its identifier. + * + * @param {string} id - The transfer identifier. + * @returns {Promise} The transfer's current status. + * @throws {UnsupportedOperationError} If the protocol does not support this operation. + * @throws {NoSuchElementError} If no such transfer exists. + */ + getTransfer(id: string): Promise; + /** + * Recovers a deposit or address that was not picked up automatically, using the protocol's recovery mode. + * + * @param {SdaRecoveryOptions} options - The recovery options. + * @returns {Promise} The recovery outcome. + * @throws {UnsupportedOperationError} If the protocol does not support this operation. + */ + recoverDepositAddress(options: SdaRecoveryOptions): Promise; + /** + * Disables a deposit address so it no longer accepts deposits. + * + * @param {string} id - The deposit-address identifier returned in `SdaDepositAddress.id` (round-trips any chain + * context the protocol needs). + * @returns {Promise} Resolves once the address has been disabled. + * @throws {UnsupportedOperationError} If the protocol does not support this operation. + */ + disableDepositAddress(id: string): Promise; +} +/** + * Abstract base class for "Smart Deposit Address" (SDA) protocols. + * + * @abstract + * @implements {ISdaProtocol} + */ +export default abstract class SdaProtocol implements ISdaProtocol { + /** + * Creates a new SDA protocol without binding it to a wallet account. + * + * @overload + * @param {undefined} [account] - The wallet account to use to interact with the protocol. + */ + constructor(account?: undefined); + /** + * Creates a new read-only SDA protocol. + * + * @overload + * @param {IWalletAccountReadOnly} account - The wallet account to use to interact with the protocol. + */ + constructor(account: IWalletAccountReadOnly); + /** + * Creates a new SDA protocol. + * + * @overload + * @param {IWalletAccount} account - The wallet account to use to interact with the protocol. + */ + constructor(account: IWalletAccount); + /** + * The wallet account to use to interact with the protocol. The account's address is the default delivery + * destination for created addresses. + * + * @protected + * @type {IWalletAccountReadOnly | IWalletAccount | undefined} + */ + protected _account: IWalletAccountReadOnly | IWalletAccount | undefined; + /** + * Lists the conversion routes the protocol supports: source chains, accepted input tokens, output assets and + * per-route deposit limits. A protocol that discovers routes by blockchain pairs might require the `sourceChain` + * and `destinationChain` options to be set. + * + * @abstract + * @param {SdaRoutesOptions} [options] - Optional filters for route discovery. + * @returns {Promise} The supported routes. + * @throws {ValueError} If the protocol discovers routes by blockchain pairs and the source or destination blockchain + * is not set. + */ + getSupportedRoutes(options?: SdaRoutesOptions): Promise; + /** + * Fetches a non-binding quote (estimate) for a deposit — what a given deposit would deliver. + * + * @param {SdaDepositOptions} options - The quote options. + * @returns {Promise} The quoted deposit details. + * @throws {UnsupportedOperationError} If the protocol does not support this operation. + * @throws {ValueError} If the protocol requires an output asset and none is provided. + */ + quoteDeposit(options: SdaDepositOptions): Promise; + /** + * Creates deposit addresses for the given route and destination, ready to receive per the protocol's activation + * lifecycle — a protocol that activates addresses also activates the created address so it is monitored. Returns + * one entry per distinct address: a protocol that issues a single address across a chain family returns one entry + * covering all of `sourceChains`, while a protocol that issues one address per source chain returns one entry each. + * + * @abstract + * @param {SdaCreateDepositAddressOptions} options - The address creation options. + * @returns {Promise} The created deposit addresses, one per distinct address. + * @throws {ValueError} If `destinationAddress` is omitted and no account was bound at construction. + * @throws {ValueError} If the protocol requires an output asset and none is provided. + */ + createDepositAddress(options: SdaCreateDepositAddressOptions): Promise; + /** + * Derives a deposit address client-side, without any protocol call and without activating or monitoring it — + * used to verify (derive + compare) or recover an address for a self-custodial protocol. + * + * @param {SdaCreateDepositAddressOptions} options - The same options passed to + * {@link ISdaProtocol#createDepositAddress}; a protocol needing extra derivation inputs declares them on its own + * options type (which extends `SdaCreateDepositAddressOptions`). + * @returns {Promise} The derived deposit address. + * @throws {UnsupportedOperationError} If the protocol does not support this operation. + * @throws {ValueError} If `destinationAddress` is omitted and no account was bound at construction. + */ + deriveDepositAddress(options: SdaCreateDepositAddressOptions): Promise; + /** + * Looks up an existing deposit address by its identifier — the `SdaDepositAddress.id` returned by + * {@link ISdaProtocol#createDepositAddress}, which round-trips any chain context the protocol needs. + * + * @param {string} id - The deposit-address identifier returned in `SdaDepositAddress.id` (round-trips any chain + * context the protocol needs). + * @returns {Promise} The deposit address descriptor. + * @throws {UnsupportedOperationError} If the protocol does not support this operation. + * @throws {NoSuchElementError} If no such address exists. + */ + getDepositAddress(id: string): Promise; + /** + * Refreshes the activation of a deposit address so the protocol keeps monitoring it. + * + * @param {string} id - The deposit-address identifier returned in `SdaDepositAddress.id`. + * @returns {Promise} The refreshed deposit address descriptor (with the new `expiry`). + * @throws {UnsupportedOperationError} If the protocol does not support this operation. + */ + renewDepositAddress(id: string): Promise; + /** + * Lists the deposits observed at a deposit address. + * + * @param {string} address - The deposit address to list transfers for. + * @param {SdaTransfersOptions} [options] - Optional pagination/filtering, plus `sourceChain` for protocols that key + * addresses by (address, chain). + * @returns {Promise} The transfers for the address. + * @throws {UnsupportedOperationError} If the protocol does not support this operation. + */ + getTransfers(address: string, options?: SdaTransfersOptions): Promise; + /** + * Lists transfers aggregated by recipient — every deposit routed to the given recipient across all of that + * recipient's deposit addresses and source chains. + * + * @param {Blockchain} destinationChain - The destination chain the transfers are delivered to. + * @param {string} recipient - The recipient (destination) address to aggregate transfers for. + * @param {SdaTransfersOptions} [options] - Optional pagination/filtering. + * @returns {Promise} The transfers routed to the recipient. + * @throws {UnsupportedOperationError} If the protocol does not support this operation. + */ + getTransfersByRecipient(destinationChain: Blockchain, recipient: string, options?: SdaTransfersOptions): Promise; + /** + * Retrieves a single transfer by its identifier. + * + * @param {string} id - The transfer identifier. + * @returns {Promise} The transfer's current status. + * @throws {UnsupportedOperationError} If the protocol does not support this operation. + * @throws {NoSuchElementError} If no such transfer exists. + */ + getTransfer(id: string): Promise; + /** + * Recovers a deposit or address that was not picked up automatically, using the protocol's recovery mode. + * + * @param {SdaRecoveryOptions} options - The recovery options. + * @returns {Promise} The recovery outcome. + * @throws {UnsupportedOperationError} If the protocol does not support this operation. + */ + recoverDepositAddress(options: SdaRecoveryOptions): Promise; + /** + * Disables a deposit address so it no longer accepts deposits. + * + * @param {string} id - The deposit-address identifier returned in `SdaDepositAddress.id` (round-trips any chain + * context the protocol needs). + * @returns {Promise} Resolves once the address has been disabled. + * @throws {UnsupportedOperationError} If the protocol does not support this operation. + */ + disableDepositAddress(id: string): Promise; +} +export type IWalletAccountReadOnly = import("../wallet-account-read-only.js").IWalletAccountReadOnly; +export type IWalletAccount = import("../wallet-account.js").IWalletAccount; +export type ValueError = import("../errors.js").ValueError; +export type NoSuchElementError = import("../errors.js").NoSuchElementError; +/** + * A blockchain identifier: a numeric chain id (e.g. `1`) or a protocol-specific chain name (e.g. `'ethereum'`). + */ +export type Blockchain = string | number; +/** + * A normalized token reference. `token` is the identifier the protocol expects in SDA calls; `address` is the + * on-chain contract address when applicable (absent for native gas tokens). + */ +export type SdaToken = { + /** + * - The protocol-specific token identifier to use in SDA calls. + */ + token: string; + /** + * - The chain on which the token lives. + */ + chain: Blockchain; + /** + * - The token symbol (e.g., 'USDC', 'USDT'). + */ + symbol: string; + /** + * - The number of decimal places for the token's base unit. + */ + decimals: number; + /** + * - The token contract address, if applicable. + */ + address?: string; + /** + * - The token's full name. + */ + name?: string; +}; +/** + * Per-route deposit limits, denominated in the base unit of the route's input token. Either bound may be absent + * when the protocol does not enforce it; a protocol that only enforces limits in another denomination (e.g. USD) + * omits `limits` rather than converting. + */ +export type SdaDepositAddressLimits = { + /** + * - Minimum deposit amount, in the input token's base unit. + */ + min?: number | bigint; + /** + * - Maximum deposit amount, in the input token's base unit. + */ + max?: number | bigint; +}; +/** + * Optional filters for narrowing route discovery. + */ +export type SdaRoutesOptions = { + /** + * - Restrict to routes that accept deposits from this chain. + */ + sourceChain?: Blockchain; + /** + * - Restrict to routes that accept this input token. + */ + sourceToken?: string; + /** + * - Restrict to routes that deliver to this chain. + */ + destinationChain?: Blockchain; + /** + * - Restrict to routes that deliver this asset. + */ + outputAsset?: string; +}; +/** + * A supported conversion route: one or more source chains and their accepted input tokens, the destination chain, + * and the asset delivered there. + */ +export type SdaRoute = { + /** + * - The source chains this route accepts deposits from. A list because some + * protocols issue one address valid across a VM family. + */ + sourceChains: Blockchain[]; + /** + * - The deposit tokens accepted on the source side. + */ + inputTokens: SdaToken[]; + /** + * - The chain the converted asset is delivered to. + */ + destinationChain: Blockchain; + /** + * - The asset delivered to the destination (e.g., USDT). If unset, the route + * delivers each input token as its own equivalent on the destination chain. + */ + outputAsset?: SdaToken; + /** + * - Deposit limits for this route. + */ + limits?: SdaDepositAddressLimits; + /** + * - Whether addresses issued for this route can receive more than one deposit. + */ + reusable?: boolean; + /** + * - Typical end-to-end duration in seconds. + */ + estimatedDuration?: number; +}; +/** + * Options for fetching a deposit quote — a non-binding estimate of what a given deposit would deliver. + */ +export type SdaDepositOptions = { + /** + * - The chain the deposit originates from. + */ + sourceChain: Blockchain; + /** + * - The protocol identifier of the token being deposited. + */ + inputToken: string; + /** + * - The chain the converted asset is delivered to. + */ + destinationChain: Blockchain; + /** + * - The protocol identifier of the asset to deliver. Omit for protocols that deliver each input token as its + * own equivalent. + */ + outputAsset?: string; + /** + * - The amount to deposit, in the input token's base unit. + */ + inputAmount: number | bigint; +}; +/** + * The category of a fee charged by the protocol. + */ +export type SdaFeeType = "network" | "protocol" | "affiliate" | "other"; +/** + * A single itemised fee. + */ +export type SdaFee = { + /** + * - The category of the fee. + */ + type: SdaFeeType; + /** + * - The fee amount, in the fee token's base unit. + */ + amount: bigint; + /** + * - The token in which the fee is denominated. + */ + token: string; + /** + * - The chain on which the fee is charged. + */ + chain?: Blockchain; + /** + * - Whether the fee is already reflected in the quoted output amount. + */ + included?: boolean; + /** + * - A human-readable description of the fee. + */ + description?: string; +}; +/** + * A non-binding estimate of the asset delivered for a given deposit. + */ +export type SdaDepositQuote = { + /** + * - The chain the deposit originates from. + */ + inputChain: Blockchain; + /** + * - The protocol identifier of the deposited token. + */ + inputToken: string; + /** + * - The amount deposited, in the input token's base unit. + */ + inputAmount: bigint; + /** + * - The chain the converted asset is delivered to. + */ + destinationChain: Blockchain; + /** + * - The protocol identifier of the delivered asset. + */ + outputAsset: string; + /** + * - The estimated amount delivered, in the destination asset's base unit. + */ + outputAmount: bigint; + /** + * - Itemised fee breakdown. + */ + fees: SdaFee[]; + /** + * - The effective conversion rate as a string, to avoid precision loss. + */ + rate?: string; + /** + * - Unix timestamp (seconds) at which the quote expires. + */ + expiry?: number; + /** + * - The protocol quote identifier, if the protocol issues one. + */ + id?: string; +}; +/** + * Options for creating a deposit address. + */ +export type SdaCreateDepositAddressOptions = { + /** + * - One or more source chains the address should accept deposits from. Protocols + * that issue one address per VM family use the full list; single-chain protocols use a one-element list. + */ + sourceChains: Blockchain[]; + /** + * - The chain the converted asset is delivered to. + */ + destinationChain: Blockchain; + /** + * - The protocol identifier of the asset to deliver (e.g., USDT). Omit for protocols that deliver each input + * token as its own equivalent. + */ + outputAsset?: string; + /** + * - The address that receives the delivered asset. Defaults to the bound + * account's address. + */ + destinationAddress?: string; +}; +/** + * A deposit address plus its normalized descriptor: where it accepts deposits from, what it accepts, where it + * delivers, and its lifecycle metadata. + */ +export type SdaDepositAddress = { + /** + * - The deposit address the user sends funds to. + */ + address: string; + /** + * - The protocol identifier for this SDA, used for status, recovery and disabling. + */ + id: string; + /** + * - The chains this address accepts deposits from. + */ + sourceChains: Blockchain[]; + /** + * - The tokens this address accepts. + */ + supportedInputTokens: SdaToken[]; + /** + * - The chain the converted asset is delivered to. + */ + destinationChain: Blockchain; + /** + * - The asset delivered to the destination. If unset, the address delivers each input token as its own + * equivalent on the destination chain. + */ + outputAsset?: SdaToken; + /** + * - The resolved address that receives the delivered asset. + */ + destinationAddress: string; + /** + * - Deposit limits for this address. + */ + limits?: SdaDepositAddressLimits; + /** + * - Whether the address can receive more than one deposit. + */ + reusable: boolean; + /** + * - Unix timestamp (seconds) at which the address's activation expires, when the protocol's + * address activation is time-limited. + */ + expiry?: number; +}; +/** + * The lifecycle status of a deposit/transfer through an SDA. + */ +export type SdaTransferStatus = "pending" | "detected" | "processing" | "completed" | "failed" | "refund-pending" | "refunded" | "expired"; +/** + * A single deposit observed at, and processed through, an SDA. + */ +export type SdaTransfer = { + /** + * - The protocol identifier for this transfer. + */ + id: string; + /** + * - The current status of the transfer. + */ + status: SdaTransferStatus; +}; +/** + * Optional pagination/filtering for transfer history. + */ +export type SdaTransfersOptions = { + /** + * - The source chain of the deposit address, required by protocols that key + * addresses by (address, chain). + */ + sourceChain?: Blockchain; + /** + * - The maximum number of transfers to return. + */ + limit?: number; + /** + * - The number of transfers to skip, for offset-based pagination. + */ + skip?: number; + /** + * - Restrict to transfers in this status. + */ + status?: SdaTransferStatus; +}; +/** + * Recover a deposit by the SDA identifier. + */ +export type SdaRecoverById = { + /** + * - The protocol SDA identifier (the `SdaDepositAddress.id`). + */ + id: string; +}; +/** + * Recover a deposit by its deposit address. + */ +export type SdaRecoverByAddress = { + /** + * - The deposit address to reindex. + */ + address: string; + /** + * - The chain of the deposit address, required by protocols that key addresses by + * (address, chain). + */ + sourceChain?: Blockchain; +}; +/** + * Options for re-processing a deposit that was not picked up automatically (`reindex`). A caller identifies the + * deposit either by SDA id or by its deposit address. + */ +export type SdaRecoveryOptions = SdaRecoverById | SdaRecoverByAddress; +/** + * The outcome of a recovery attempt. + */ +export type SdaRecoveryResult = { + /** + * - The result of the reindex attempt. + */ + status: "reindexed" | "pending" | "failed"; + /** + * - The address that was reindexed. + */ + address?: string; + /** + * - The protocol SDA identifier. + */ + id?: string; + /** + * - The transfer that was recovered, if one resulted. + */ + transfer?: SdaTransfer; + /** + * - A human-readable description of the outcome. + */ + message?: string; +};