Source

types.ts

/* eslint-disable @typescript-eslint/no-explicit-any */
import type { IKey } from '@activeledger/sdk';

import type { NodeStatus } from './APACTypes';
import type {
  ACDevNode,
  ACNode,
  AkashicBaseUrl,
  AkashicBaseUrlDev,
  AkashicPayBaseUrl,
  AkashicPayBaseUrlDev,
  Environment,
} from './constants';
import type { AkashicErrorCode } from './error';
import type { ILogger } from './logger';

export interface IBaseAcTransaction {
  $selfsign?: boolean;
  $sigs: any;
  $tx: IAcTxBody;
}
interface IAcTxBody {
  $entry?: string;
  $contract: string;
  $namespace: string;
  $i: any;
  $o?: any;
  $r?: any;
  _dbIndex?: number;
  /** ISO8601-date. Checked upon node receiving tx.
   * As this object is hashed to create the umid (unique across all transactions
   * per contract), it should also help to prevent replay attacks
   */
  $expire?: string;
  metadata?: IMetadata;
}

export interface IMetadata {
  /** The L1 address or alias that the user typed into the UI when sending the
   * transaction, if the system resolved that to an L2 address. This is the only
   * way to identify the depositor to a BP if the deposit is mapped to L2s */
  initiatedToNonL2?: string;
  /** Must be present in BP payouts. Uniquely identifies the end-user to whom
   * the payout is made. */
  identifier?: string;
  /** The amount deducted for safety from keys and owners to prevent
   * overspending, and probably partially refunded later, when the actual fee
   * paid is known */
  feesEstimate?: string;
}

export type Otk = Required<IKey>;
/**
 * KeyBackup
 */
export interface KeyBackup {
  /** L2-Address */
  l2Address: string;
  /** Private key, in "0x1a2b..." format */
  privateKey: string;
  /** The raw full Otk */
  raw: Otk;
}

// //// HTTP //// //
/** HTTPResponse */
export interface HTTPResponse<ResponseDataT = unknown> {
  /** Response data object, unknown by default */
  data: ResponseDataT;
  /** HTTP status code */
  status: number;
}

/** IHttpClient
 * Interface describing an HTTP Client which may be injected. Used to perform
 * HTTP requests
 */
export interface IHttpClient {
  /** POST
   * @function <>
   * @param {string} url
   * @param {unknown} payload
   * @returns {Promise<HTTPResponse>}
   */
  post: <ResponseDataT = unknown>(
    url: string,
    payload: unknown
  ) => Promise<HTTPResponse<ResponseDataT>>;
  /** GET
   * @function
   * @param {string} url
   * @returns {Promise<HTTPResponse>}
   */
  get: <ResponseDataT = unknown>(
    url: string
  ) => Promise<HTTPResponse<ResponseDataT>>;
}

// //// CRYPTO //// //

export enum TronSymbol {
  Tron = 'TRX',
  Tron_Shasta = 'TRX-SHASTA',
}

export enum EthereumSymbol {
  Ethereum_Mainnet = 'ETH',
  Ethereum_Sepolia = 'SEP',
}

/**
 * Networks
 * @category Crypto
 * @enum {string}
 * @property {string} Ethereum_Mainnet 'ETH'
 * @property {string} Ethereum_Sepolia 'SEP'
 * @property {string} Tron 'TRX'
 * @property {string} Tron_Shasta 'TRX-SHASTA'
 */
export const NetworkSymbol = {
  ...TronSymbol,
  ...EthereumSymbol,
};

export type NetworkSymbol = TronSymbol | EthereumSymbol;

export const MainNets = [NetworkSymbol.Tron, NetworkSymbol.Ethereum_Mainnet];
export const TestNets = [
  NetworkSymbol.Tron_Shasta,
  NetworkSymbol.Ethereum_Sepolia,
];

/**
 * Tokens
 * @category Crypto
 * @enum {string}
 * @property {string} USDT 'USDT'
 * @property {string} TETHER UNUSED - For testing purposes only
 */
export enum TokenSymbol {
  USDT = 'USDT',
  /** Used for USDT on TRX-Shasta */
  TETHER = 'Tether',
}

// //// Requests & Returns //// //

/** IGetTransactions */
export interface IGetTransactions {
  /** Page, for pagination */
  page?: number;
  /** Limit for pagination, only accepts 10, 25, 50, or 100 */
  limit?: number;
  /** No transaction from before this date will be returned */
  startDate?: Date;
  /** No transaction from after this date will be returned */
  endDate?: Date;
  /** Transaction layer: 'L1' or 'L2' */
  layer?: TransactionLayer;
  /** Transaction status: Pending, Confirmed, or Failed */
  status?: TransactionStatus;
  /** Transaction type: Deposit or Withdrawal (Payout) */
  type?: TransactionType;
  /** Set to true if you do not want transactions with value less than 1 USD */
  hideSmallTransactions?: boolean;
}

/** IDepositAddress */
export interface IDepositAddress {
  /** Address (L1) that can be transferred to */
  address: string;
  /** userId or similar which will be identified with deposits to this address */
  identifier: string;
}
/** IBalance */
export interface IBalance {
  /** Network */
  readonly networkSymbol: NetworkSymbol;
  /** Token */
  readonly tokenSymbol?: TokenSymbol;
  /** Balance */
  readonly balance: string;
}

/** ILookForL2AddressResult */
export interface ILookForL2AddressResult {
  /** L2 Address */
  readonly l2Address?: string;
  readonly alias?: string;
}

/** IPayoutResponse */
export interface IPayoutResponse {
  /** Error Code if payout fails */
  error?: AkashicErrorCode;
  /** AkashicChain-hash of transaction. Undefined if failure */
  l2Hash?: string;
}

export interface IGetByOwnerAndIdentifier {
  identifier: string;
  coinSymbol: NetworkSymbol;
}

export interface IGetKeysByOwnerAndIdentifier {
  identifier: string;
}
// //// Transactions //// //

/** ITransaction */
export interface ITransaction {
  /** Sending address */
  readonly fromAddress: string;
  /** Receiving address */
  readonly toAddress: string;
  /** Transaction-layer: L1 or L2 */
  readonly layer: TransactionLayer;
  /** Date in ISO8601 format */
  readonly initiatedAt: string;
  /** Confirmed Date in ISO8601 format */
  readonly confirmededAt: string;
  /** Transaction amount */
  readonly amount: string;
  /** Network (L1) of transaction */
  readonly coinSymbol: NetworkSymbol;
  /** Transaction status */
  readonly status: TransactionStatus;
  /** Network's hash if L1. Not present for L2 */
  readonly txHash?: string;
  /** Gas Fee paid on network. Not present for L2 */
  readonly feesPaid?: string;
  /** Akashic Transaction Hash. For both L1 and L2 */
  readonly l2TxnHash?: string;
  /** Present only if token-transaction */
  readonly tokenSymbol?: TokenSymbol;
  /** Present if status = 'Failed', explaing the failure */
  readonly reason?: string;
  /** Akashic Fee */
  readonly internalFee?: IInternalFee;
  /** User-identifier for deposits */
  readonly identifier?: string;
}

/**
 * @category Transactions
 * @enum {string}
 * @property {string} L1 'L1Transaction'
 * @property {string} L2 'L2Transaction'
 */
export enum TransactionLayer {
  L1 = 'L1Transaction',
  L2 = 'L2Transaction',
}
/**
 * @category Transactions
 * @enum {string}
 * @property {string} PENDING 'Pending'
 * @property {string} CONFIRMED 'Confirmed'
 * @property {string} FAILED 'Failed'
 */
export enum TransactionStatus {
  PENDING = 'Pending',
  CONFIRMED = 'Confirmed',
  FAILED = 'Failed',
}

/**
 * @category Transactions
 * @enum {string}
 * @property {string} SUCCESS 'Success'
 * @property {string} FAILURE 'Failure'
 */
export enum TransactionResult {
  SUCCESS = 'Success',
  FAILURE = 'Failure',
}

/**
 * @category Transactions
 * @enum {string}
 * @property {string} DEPOSIT 'Deposit'
 * @property {string} WITHDRAWAL 'Withdrawal'
 */
export enum TransactionType {
  DEPOSIT = 'Deposit',
  WITHDRAWAL = 'Withdrawal',
}

/** IInternalFee */
export interface IInternalFee {
  /** Deposit fee */
  deposit?: string;
  /** Withdraw fee */
  withdraw?: string;
}

// //// Construction //// //

export type ACNodeT<Env extends Environment> =
  Env extends Environment.Production ? ACNode : ACDevNode;

export type AkashicUrlT<Env extends Environment> =
  Env extends Environment.Production
    ? typeof AkashicBaseUrl
    : typeof AkashicBaseUrlDev;

export type AkashicPayUrlT<Env extends Environment> =
  Env extends Environment.Production
    ? typeof AkashicPayBaseUrl
    : typeof AkashicPayBaseUrlDev;

export type APConstructorArgs<
  Env extends Environment = Environment.Production,
> = {
  /**
   * A logger instance used for debugging and error logging.
   * Although it is optional, we strongly recommend you provide one, otherwise
   * messages will be logged to the console.
   * We also recommend you construct the logger instance with a meaningful name,
   * like `'AkashicPaySDK'`, assuming your preferred logger supports this.
   * If your preferred logger does not match the {@Link ILogger} interface, you
   * can create a wrapper that does.
   */
  logger?: ILogger;
  environment?: Env;
  targetNode?: Env extends Environment.Production ? ACNode : ACDevNode;
  akashicUrl?: Env extends Environment.Production
    ? typeof AkashicBaseUrl
    : typeof AkashicBaseUrlDev;
};

/**
 * OtkPair
 * @property {string} [recoveryPhrase] Supply this or privateKey
 * @property {string} [privateKey] Supply this or recoveryPhrase
 */
type OTKPair = {
  l2Address: string;
} & ({ recoveryPhrase: string } | { privateKey: string });

/**
 * APInitialisationArgs
 */
export type APInitialisationArgs<
  Env extends Environment = Environment.Production,
> = Env extends Environment.Production ? OTKPair : Partial<OTKPair>;

// This has to be separetely defined as a combination of ApConstructorArgs and
// APInitializationArgs to be correctly displayed by JSDocs
/**
 * @typedef {APBuilderArgs<Environment>}
 * @property {ILogger} [logger]
 * @property {Environment} [environment] Defaults to Environment.Production
 * @property {ACNode | ACDevNode} [targetNode] Dependent on environment
 * @property {string} [recoveryPhrase] Supply this or privateKey
 * @property {string} [privateKey] Supply this or recoveryPhrase
 * @property {string} [l2Address]
 */

/**
 * ApBuilderArgs
 */
export type APBuilderArgs<Env extends Environment = Environment.Production> =
  APConstructorArgs<Env> & APInitialisationArgs<Env>;

export interface NodeResponsiveness<Env extends Environment>
  extends NodeStatus {
  /** e2e duration of status-check request */
  ping: number;
  /** node's external address; i.e. its URL */
  node: ACNodeT<Env>;
}