types.ts raw

   1  import {
   2    BellIcon,
   3    CirclePlusIcon,
   4    CrownIcon,
   5    HandCoinsIcon,
   6    InfoIcon,
   7    LucideIcon,
   8    NotebookTabsIcon,
   9    PenLineIcon,
  10    SearchIcon,
  11    WalletMinimalIcon,
  12  } from "lucide-react";
  13  
  14  export type BackendType = "LND" | "LDK" | "PHOENIX" | "CASHU" | "CLN" | "BARK";
  15  
  16  export type Nip47RequestMethod =
  17    | "get_info"
  18    | "get_balance"
  19    | "get_budget"
  20    | "make_invoice"
  21    | "pay_invoice"
  22    | "pay_keysend"
  23    | "lookup_invoice"
  24    | "list_transactions"
  25    | "sign_message"
  26    | "multi_pay_invoice"
  27    | "multi_pay_keysend"
  28    | "make_hold_invoice"
  29    | "settle_hold_invoice"
  30    | "cancel_hold_invoice";
  31  
  32  export type BudgetRenewalType =
  33    | "daily"
  34    | "weekly"
  35    | "monthly"
  36    | "yearly"
  37    | "never"
  38    | "";
  39  
  40  export type Scope =
  41    | "pay_invoice" // also used for pay_keysend, multi_pay_invoice, multi_pay_keysend
  42    | "get_balance"
  43    | "get_info"
  44    | "make_invoice"
  45    | "lookup_invoice"
  46    | "list_transactions"
  47    | "sign_message"
  48    | "notifications" // covers all notification types
  49    | "superuser";
  50  
  51  export type Nip47NotificationType = "payment_received" | "payment_sent";
  52  
  53  export type ScopeIconMap = {
  54    [key in Scope]: LucideIcon;
  55  };
  56  
  57  export const scopeIconMap: ScopeIconMap = {
  58    get_balance: WalletMinimalIcon,
  59    get_info: InfoIcon,
  60    list_transactions: NotebookTabsIcon,
  61    lookup_invoice: SearchIcon,
  62    make_invoice: CirclePlusIcon,
  63    pay_invoice: HandCoinsIcon,
  64    sign_message: PenLineIcon,
  65    notifications: BellIcon,
  66    superuser: CrownIcon,
  67  };
  68  
  69  export type WalletCapabilities = {
  70    methods: Nip47RequestMethod[];
  71    scopes: Scope[];
  72    notificationTypes: Nip47NotificationType[];
  73  };
  74  
  75  export const validBudgetRenewals: BudgetRenewalType[] = [
  76    "daily",
  77    "weekly",
  78    "monthly",
  79    "yearly",
  80    "never",
  81  ];
  82  
  83  // Scopes granted to a read-only connection: receive payments and view
  84  // balance/history, but never send/spend.
  85  export const READ_ONLY_SCOPES: Scope[] = [
  86    "get_balance",
  87    "get_info",
  88    "make_invoice",
  89    "lookup_invoice",
  90    "list_transactions",
  91    "notifications",
  92  ];
  93  
  94  export const scopeDescriptions: Record<Scope, string> = {
  95    get_balance: "Read your balance",
  96    get_info: "Read your node info",
  97    list_transactions: "Read transaction history",
  98    lookup_invoice: "Lookup status of invoices",
  99    make_invoice: "Create invoices",
 100    pay_invoice: "Send payments",
 101    sign_message: "Sign messages",
 102    notifications: "Receive wallet notifications",
 103    superuser: "Create other app connections",
 104  };
 105  
 106  export const expiryOptions: Record<string, number> = {
 107    "1 week": 7,
 108    "1 month": 30,
 109    "1 year": 365,
 110  };
 111  
 112  export const budgetOptionsSat: Record<string, number> = {
 113    "10k": 10_000,
 114    "100k": 100_000,
 115    "1M": 1_000_000,
 116  };
 117  
 118  export interface ErrorResponse {
 119    message: string;
 120  }
 121  
 122  export interface App {
 123    id: number;
 124    name: string;
 125    description: string;
 126    appPubkey: string;
 127    uniqueWalletPubkey: boolean;
 128    walletPubkey: string;
 129    createdAt: string;
 130    updatedAt: string;
 131    lastUsedAt?: string;
 132    lastSettledTransactionAt?: string;
 133    expiresAt?: string;
 134    isolated: boolean;
 135    balanceSat: number;
 136    balanceMsat: number;
 137  
 138    scopes: Scope[];
 139    maxAmountSat: number;
 140    maxAmountMsat: number;
 141    budgetUsageSat: number;
 142    budgetUsageMsat: number;
 143    budgetRenewal: BudgetRenewalType;
 144    metadata?: AppMetadata;
 145  }
 146  
 147  export interface AppPermissions {
 148    scopes: Scope[];
 149    maxAmountSat: number;
 150    budgetRenewal: BudgetRenewalType;
 151    expiresAt?: Date;
 152    isolated: boolean;
 153  }
 154  
 155  export interface InfoResponse {
 156    backendType: BackendType;
 157    setupCompleted: boolean;
 158    oauthRedirect: boolean;
 159    albyAccountConnected: boolean;
 160    ldkVssEnabled: boolean;
 161    ldkVssUrl: string;
 162    vssSupported: boolean;
 163    databaseType: string;
 164    running: boolean;
 165    albyAuthUrl: string;
 166    nextBackupReminder: string;
 167    albyUserIdentifier: string;
 168    network?: Network;
 169    version: string;
 170    relays: { url: string; online: boolean }[];
 171    unlocked: boolean;
 172    enableAdvancedSetup: boolean;
 173    startupState: string;
 174    startupError: string;
 175    startupErrorTime: string;
 176    autoUnlockPasswordSupported: boolean;
 177    autoUnlockPasswordEnabled: boolean;
 178    currency: string;
 179    nodeAlias: string;
 180    mempoolUrl: string;
 181    bitcoinDisplayFormat: BitcoinDisplayFormat;
 182    chainDataSourceType?: string;
 183    chainDataSourceAddress?: string;
 184    jitChannelsLiquiditySource?: string;
 185    jitChannelsMinPaymentSizeMsat?: number;
 186    jitChannelsMaxPaymentSizeMsat?: number;
 187    jitChannelsEnabled: boolean;
 188    hideUpdateBanner: boolean;
 189    supportsBolt12: boolean;
 190    nodeMigrationFileCreated: boolean;
 191  }
 192  
 193  export type BitcoinDisplayFormat = "sats" | "bip177";
 194  
 195  export type HealthAlarmKind =
 196    | "alby_service"
 197    | "node_not_ready"
 198    | "channels_offline"
 199    | "nostr_relay_offline"
 200    | "vss_no_subscription";
 201  
 202  export type HealthAlarm = {
 203    kind: HealthAlarmKind;
 204    rawDetails?: unknown;
 205  };
 206  export type AlbyInfoIncident = {
 207    name: string;
 208    started: string;
 209    status: string;
 210    impact: string;
 211    url: string;
 212  };
 213  
 214  export type HealthResponse = {
 215    alarms: HealthAlarm[];
 216  };
 217  
 218  export type Network = "bitcoin" | "testnet" | "signet";
 219  
 220  export type AppMetadata = {
 221    app_store_app_id?: string;
 222    lud16?: string;
 223  } & Record<string, unknown>;
 224  
 225  export type AutoSwapConfig = {
 226    type: "out";
 227    enabled: boolean;
 228    balanceThresholdSat: number;
 229    swapAmountSat: number;
 230    destination: string;
 231  };
 232  
 233  export type SwapInfo = {
 234    albyServiceFee: number;
 235    boltzServiceFee: number;
 236    boltzNetworkFeeSat: number;
 237    minAmountSat: number;
 238    maxAmountSat: number;
 239  };
 240  
 241  export type BaseSwap = {
 242    id: string;
 243    sendAmountSat: number;
 244    lockupAddress: string;
 245    paymentHash: string;
 246    invoice: string;
 247    autoSwap: boolean;
 248    usedXpub: boolean;
 249    boltzPubkey: string;
 250    createdAt: string;
 251    updatedAt: string;
 252    lockupTxId?: string;
 253    claimTxId?: string;
 254    receiveAmountSat?: number;
 255  };
 256  
 257  export type SwapIn = BaseSwap & {
 258    type: "in";
 259    state: "PENDING" | "SUCCESS" | "FAILED" | "REFUNDED";
 260    refundAddress?: string;
 261  };
 262  
 263  export type SwapOut = BaseSwap & {
 264    type: "out";
 265    state: "PENDING" | "SUCCESS" | "FAILED";
 266    destinationAddress: string;
 267  };
 268  
 269  export type Swap = SwapIn | SwapOut;
 270  
 271  export type SwapResponse = {
 272    swapId: string;
 273    paymentHash: string;
 274  };
 275  
 276  export interface MnemonicResponse {
 277    mnemonic: string;
 278  }
 279  
 280  export interface CreateAppRequest {
 281    name: string;
 282    pubkey?: string;
 283    maxAmountSat?: number;
 284    maxAmountMsat?: number;
 285    budgetRenewal?: BudgetRenewalType;
 286    expiresAt?: string;
 287    scopes: Scope[];
 288    returnTo?: string;
 289    isolated?: boolean;
 290    metadata?: AppMetadata;
 291    unlockPassword?: string; // required to create superuser apps
 292  }
 293  
 294  export interface CreateAppResponse {
 295    id: number;
 296    name: string;
 297    pairingUri: string;
 298    pairingPublicKey: string;
 299    pairingSecretKey: string;
 300    relayUrls: string[];
 301    walletPubkey: string;
 302    lud16: string;
 303    returnTo: string;
 304  }
 305  
 306  export type UpdateAppRequest = {
 307    name?: string;
 308    maxAmountSat?: number;
 309    maxAmountMsat?: number;
 310    budgetRenewal?: string;
 311    expiresAt?: string | undefined;
 312    updateExpiresAt?: boolean;
 313    scopes?: Scope[];
 314    metadata?: AppMetadata;
 315    isolated?: boolean;
 316  };
 317  
 318  export type Channel = {
 319    localBalanceSat: number;
 320    localBalanceMsat: number;
 321    localSpendableBalanceSat: number;
 322    localSpendableBalanceMsat: number;
 323    remoteBalanceSat: number;
 324    remoteBalanceMsat: number;
 325    remotePubkey: string;
 326    id: string;
 327    fundingTxId: string;
 328    fundingTxVout: number;
 329    active: boolean;
 330    public: boolean;
 331    confirmations?: number;
 332    confirmationsRequired?: number;
 333    forwardingFeeBaseMsat: number;
 334    forwardingFeeProportionalMillionths: number;
 335    unspendablePunishmentReserveSat: number;
 336    counterpartyUnspendablePunishmentReserveSat: number;
 337    error?: string;
 338    status: "online" | "opening" | "offline";
 339    isOutbound: boolean;
 340  };
 341  
 342  export type UpdateChannelRequest = {
 343    forwardingFeeBaseMsat: number;
 344  };
 345  
 346  export type Peer = {
 347    nodeId: string;
 348    address: string;
 349    isPersisted: boolean;
 350    isConnected: boolean;
 351  };
 352  
 353  export type NodeConnectionInfo = {
 354    pubkey: string;
 355    address: string;
 356    port: number;
 357  };
 358  
 359  export type ConnectPeerRequest = {
 360    pubkey: string;
 361    address: string;
 362    port: number;
 363  };
 364  
 365  export type SignMessageRequest = {
 366    message: string;
 367  };
 368  
 369  export type SignMessageResponse = {
 370    message: string;
 371    signature: string;
 372  };
 373  
 374  export type PayInvoiceResponse = Transaction;
 375  
 376  export type CreateOfferRequest = {
 377    description: string;
 378  };
 379  
 380  export type CreateInvoiceRequest = {
 381    amountSat?: number;
 382    amountMsat?: number;
 383    description: string;
 384    toAppId?: number;
 385  };
 386  
 387  export type PayInvoiceRequest = {
 388    amountSat?: number;
 389    amountMsat?: number;
 390    metadata?: Record<string, unknown>;
 391    fromAppId?: number;
 392  };
 393  
 394  export type OpenChannelRequest = {
 395    pubkey: string;
 396    amountSats: number;
 397    public: boolean;
 398  };
 399  
 400  export type OpenChannelResponse = {
 401    fundingTxId: string;
 402  };
 403  
 404  // eslint-disable-next-line @typescript-eslint/no-empty-object-type
 405  export type CloseChannelResponse = {};
 406  
 407  export type PendingBalancesDetails = {
 408    channelId: string;
 409    nodeId: string;
 410    amountSat: number;
 411    fundingTxId: string;
 412    fundingTxVout: number;
 413  };
 414  
 415  export type OnchainBalanceResponse = {
 416    spendableSat: number;
 417    totalSat: number;
 418    reservedSat: number;
 419    pendingBalancesFromChannelClosuresSat: number;
 420    pendingBalancesDetails: PendingBalancesDetails[];
 421    pendingSweepBalancesDetails: PendingBalancesDetails[];
 422  };
 423  
 424  // from https://mempool.space/docs/api/rest#get-address-utxo
 425  export type MempoolUtxo = {
 426    txid: string;
 427    vout: number;
 428    status: {
 429      confirmed: boolean;
 430      block_height?: number;
 431      block_hash?: string;
 432      block_time?: number;
 433    };
 434    value: number;
 435  };
 436  
 437  // from https://mempool.space/docs/api/rest#get-node-stats
 438  export type MempoolNode = {
 439    alias: string;
 440    public_key: string;
 441    color: string;
 442    active_channel_count: number;
 443    sockets: string;
 444  };
 445  
 446  // from https://mempool.space/docs/api/rest#get-transaction
 447  export type MempoolTransaction = {
 448    txid: string;
 449    //version: 1,
 450    //locktime: 0,
 451    // vin: [],
 452    //vout: [],
 453    size: number;
 454    weight: number;
 455    fee: number;
 456    status:
 457      | {
 458          confirmed: true;
 459          block_height: number;
 460          block_hash: string;
 461          block_time: number;
 462        }
 463      | { confirmed: false };
 464  };
 465  
 466  export type LongUnconfirmedZeroConfChannel = { id: string; message: string };
 467  
 468  export type SetupNodeInfo = Partial<{
 469    backendType: BackendType;
 470  
 471    mnemonic?: string;
 472    nextBackupReminder?: string;
 473  
 474    lndAddress?: string;
 475    lndCertFile?: string;
 476    lndMacaroonFile?: string;
 477  
 478    phoenixdAddress?: string;
 479    phoenixdAuthorization?: string;
 480  
 481    clnAddress?: string;
 482    clnLightningDir?: string;
 483    clnAddressHold?: string;
 484  }>;
 485  
 486  export type LSPType = "LSPS1" | "LSPS2";
 487  
 488  export type LSPChannelOfferPaymentMethod =
 489    | "card"
 490    | "wallet"
 491    | "prepaid"
 492    | "included";
 493  
 494  export type LSPChannelOffer = {
 495    lspName: string;
 496    lspDescription: string;
 497    lspContactUrl: string;
 498    lspBalanceSat: number;
 499    feeTotalSat: number;
 500    feeTotalUsd: number;
 501    currentPaymentMethod: LSPChannelOfferPaymentMethod;
 502    terms: string;
 503  };
 504  
 505  export type RecommendedChannelPeer = {
 506    network: Network;
 507    image: string;
 508    name: string;
 509    minimumChannelSizeSat: number;
 510    maximumChannelSizeSat: number;
 511    note: string;
 512    publicChannelsAllowed: boolean;
 513    description: string;
 514  } & (
 515    | {
 516        paymentMethod: "onchain";
 517        pubkey: string;
 518        host: string;
 519      }
 520    | ({
 521        paymentMethod: "lightning";
 522        identifier: string;
 523        contactUrl: string;
 524        terms?: string;
 525        pubkey?: string;
 526        maximumChannelExpiryBlocks?: number;
 527        feeTotalSat1m?: number;
 528        feeTotalSat2m?: number;
 529        feeTotalSat3m?: number;
 530      } & (
 531        | { type: "LSPS1" }
 532        | { type: "LSPS2"; nodeAddress: string } // nodeid@ip:port
 533      ))
 534  );
 535  
 536  export type AlbyInfo = {
 537    hub: {
 538      latestVersion: string;
 539      latestReleaseNotes: string;
 540    };
 541  };
 542  
 543  export type BitcoinRate = {
 544    code: string;
 545    symbol: string;
 546    rate: string;
 547    rate_float: number;
 548    rate_cents: number;
 549  };
 550  
 551  export type Currency = {
 552    iso_code: string;
 553    symbol: string;
 554    name: string;
 555    priority: number;
 556  };
 557  
 558  // TODO: use camel case (needs mapping in the Alby OAuth Service - see how AlbyInfo is done above)
 559  export type AlbyMe = {
 560    identifier: string;
 561    nostr_pubkey: string;
 562    lightning_address: string;
 563    email: string;
 564    name: string;
 565    avatar: string;
 566    keysend_pubkey: string;
 567    shared_node: boolean;
 568    hub: {
 569      name?: string;
 570      config?: {
 571        region?: string;
 572      };
 573    };
 574    subscription: {
 575      plan_code: string;
 576    };
 577  };
 578  
 579  export type LSPOrderRequest = {
 580    amountSat?: number;
 581    lspType: LSPType;
 582    lspIdentifier: string;
 583    public: boolean;
 584  };
 585  
 586  export type RedeemOnchainFundsRequest = {
 587    toAddress: string;
 588    amountSat?: number;
 589    feeRate?: number;
 590    sendAll?: boolean;
 591  };
 592  
 593  export type AutoSwapRequest = {
 594    balanceThresholdSat?: number;
 595    swapAmountSat?: number;
 596    destination: string;
 597    destinationType?: string;
 598    unlockPassword?: string;
 599  };
 600  
 601  export type InitiateSwapRequest = {
 602    swapAmountSat?: number;
 603    destination?: string;
 604  };
 605  
 606  export type LSPOrderResponse = {
 607    invoice?: string;
 608    feeSat: number;
 609    invoiceAmountSat: number;
 610    incomingLiquiditySat: number;
 611    outgoingLiquiditySat: number;
 612  };
 613  
 614  export type AutoChannelRequest = {
 615    isPublic: boolean;
 616  };
 617  export type AutoChannelResponse = {
 618    invoice?: string;
 619    feeSat?: number;
 620    channelSizeSat: number;
 621  };
 622  
 623  export type RedeemOnchainFundsResponse = {
 624    txId: string;
 625  };
 626  
 627  export type LightningBalanceResponse = {
 628    totalSpendableSat: number;
 629    totalSpendableMsat: number;
 630    totalReceivableSat: number;
 631    totalReceivableMsat: number;
 632    nextMaxSpendableSat: number;
 633    nextMaxSpendableMsat: number;
 634    nextMaxReceivableSat: number;
 635    nextMaxReceivableMsat: number;
 636    nextMaxSpendableMPPSat: number;
 637    nextMaxSpendableMPPMsat: number;
 638    nextMaxReceivableMPPSat: number;
 639    nextMaxReceivableMPPMsat: number;
 640  };
 641  
 642  export type BalancesResponse = {
 643    onchain: OnchainBalanceResponse;
 644    lightning: LightningBalanceResponse;
 645  };
 646  
 647  export type Transaction = {
 648    id: number;
 649    type: "incoming" | "outgoing";
 650    state: "settled" | "pending" | "failed";
 651    appId: number | undefined;
 652    invoice: string;
 653    description: string;
 654    descriptionHash: string;
 655    preimage: string | undefined;
 656    paymentHash: string;
 657    amountSat: number;
 658    amountMsat: number;
 659    feesPaidSat: number;
 660    feesPaidMsat: number;
 661    updatedAt: string;
 662    createdAt: string;
 663    settledAt: string | undefined;
 664    metadata?: TransactionMetadata;
 665    boostagram?: Boostagram;
 666    failureReason: string;
 667  };
 668  
 669  export type TransactionMetadata = {
 670    comment?: string; // LUD-12
 671    payer_data?: {
 672      email?: string;
 673      name?: string;
 674      pubkey?: string;
 675    }; // LUD-18
 676    recipient_data?: {
 677      identifier?: string;
 678    }; // LUD-18
 679    nostr?: {
 680      pubkey: string;
 681      tags: string[][];
 682    }; // NIP-57
 683    offer?: {
 684      id: string;
 685      payer_note: string;
 686    }; // BOLT-12
 687    swap_id?: string;
 688    user_labels?: Record<string, string>;
 689  } & Record<string, unknown>;
 690  
 691  export type Boostagram = {
 692    appName: string;
 693    name: string;
 694    podcast: string;
 695    url: string;
 696    episode?: string;
 697    feedId?: string;
 698    itemId?: string;
 699    ts?: number;
 700    message?: string;
 701    senderId: string;
 702    senderName: string;
 703    time: string;
 704    action: "boost";
 705    valueSatTotal: number;
 706    valueMsatTotal: number;
 707  };
 708  
 709  export type OnchainTransaction = {
 710    amountSat: number;
 711    amountMsat: number;
 712    createdAt: number;
 713    type: "incoming" | "outgoing";
 714    state: "confirmed" | "unconfirmed";
 715    numConfirmations: number;
 716    txId: string;
 717  };
 718  
 719  export type ListAppsResponse = {
 720    apps: App[];
 721    totalCount: number;
 722    totalBalanceSat?: number;
 723    totalBalanceMsat?: number;
 724  };
 725  
 726  export type ListTransactionsResponse = {
 727    transactions: Transaction[];
 728    totalCount: number;
 729  };
 730  
 731  export type NewChannelOrderStatus = "pay" | "paid" | "success" | "opening";
 732  
 733  type NewChannelOrderCommon = {
 734    amountSat: string;
 735    isPublic: boolean;
 736    status: NewChannelOrderStatus;
 737    fundingTxId?: string;
 738    prevChannelIds: string[];
 739  };
 740  
 741  export type OnchainOrder = {
 742    paymentMethod: "onchain";
 743    pubkey: string;
 744    host: string;
 745  } & NewChannelOrderCommon;
 746  
 747  export type LightningOrder = {
 748    paymentMethod: "lightning";
 749    lspType: LSPType;
 750    lspIdentifier: string;
 751  } & NewChannelOrderCommon;
 752  
 753  export type NewChannelOrder = OnchainOrder | LightningOrder;
 754  
 755  export type AuthTokenResponse = {
 756    token: string;
 757  };
 758  
 759  export type GetForwardsResponse = {
 760    outboundAmountForwardedSat: number;
 761    outboundAmountForwardedMsat: number;
 762    totalFeeEarnedSat: number;
 763    totalFeeEarnedMsat: number;
 764    numForwards: number;
 765  };
 766