@unicitylabs/sphere-sdk 0.1.3 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -290,11 +290,12 @@ interface BaseProvider extends ProviderMetadata {
290
290
  getStatus(): ProviderStatus;
291
291
  }
292
292
  interface Identity {
293
- readonly publicKey: string;
293
+ /** 33-byte compressed secp256k1 public key (for L3 chain) */
294
+ readonly chainPubkey: string;
294
295
  /** L1 address (alpha1...) */
295
- readonly address: string;
296
- /** L3 predicate address (DIRECT://...) */
297
- readonly predicateAddress?: string;
296
+ readonly l1Address: string;
297
+ /** L3 DIRECT address (DIRECT://...) */
298
+ readonly directAddress?: string;
298
299
  readonly ipnsName?: string;
299
300
  readonly nametag?: string;
300
301
  }
@@ -479,7 +480,7 @@ interface BroadcastMessage {
479
480
  readonly timestamp: number;
480
481
  readonly tags?: string[];
481
482
  }
482
- type SphereEventType = 'transfer:incoming' | 'transfer:confirmed' | 'transfer:failed' | 'payment_request:incoming' | 'payment_request:accepted' | 'payment_request:rejected' | 'payment_request:paid' | 'payment_request:response' | 'message:dm' | 'message:broadcast' | 'sync:started' | 'sync:completed' | 'sync:provider' | 'sync:error' | 'connection:changed' | 'nametag:registered' | 'identity:changed';
483
+ type SphereEventType = 'transfer:incoming' | 'transfer:confirmed' | 'transfer:failed' | 'payment_request:incoming' | 'payment_request:accepted' | 'payment_request:rejected' | 'payment_request:paid' | 'payment_request:response' | 'message:dm' | 'message:broadcast' | 'sync:started' | 'sync:completed' | 'sync:provider' | 'sync:error' | 'connection:changed' | 'nametag:registered' | 'nametag:recovered' | 'identity:changed';
483
484
  interface SphereEventMap {
484
485
  'transfer:incoming': IncomingTransfer;
485
486
  'transfer:confirmed': TransferResult;
@@ -517,10 +518,13 @@ interface SphereEventMap {
517
518
  nametag: string;
518
519
  addressIndex: number;
519
520
  };
521
+ 'nametag:recovered': {
522
+ nametag: string;
523
+ };
520
524
  'identity:changed': {
521
- address: string;
522
- predicateAddress?: string;
523
- publicKey: string;
525
+ l1Address: string;
526
+ directAddress?: string;
527
+ chainPubkey: string;
524
528
  nametag?: string;
525
529
  addressIndex: number;
526
530
  };
@@ -584,6 +588,245 @@ interface WalletJSONExportOptions {
584
588
  addressCount?: number;
585
589
  }
586
590
 
591
+ /**
592
+ * Transport Provider Interface
593
+ * Platform-independent P2P messaging abstraction
594
+ */
595
+
596
+ /**
597
+ * P2P messaging transport provider
598
+ */
599
+ interface TransportProvider extends BaseProvider {
600
+ /**
601
+ * Set identity for signing/encryption
602
+ */
603
+ setIdentity(identity: FullIdentity): void;
604
+ /**
605
+ * Send encrypted direct message
606
+ * @param recipientTransportPubkey - Transport-specific pubkey for messaging
607
+ * @returns Event ID
608
+ */
609
+ sendMessage(recipientTransportPubkey: string, content: string): Promise<string>;
610
+ /**
611
+ * Subscribe to incoming direct messages
612
+ * @returns Unsubscribe function
613
+ */
614
+ onMessage(handler: MessageHandler): () => void;
615
+ /**
616
+ * Send token transfer payload
617
+ * @param recipientTransportPubkey - Transport-specific pubkey for messaging
618
+ * @returns Event ID
619
+ */
620
+ sendTokenTransfer(recipientTransportPubkey: string, payload: TokenTransferPayload): Promise<string>;
621
+ /**
622
+ * Subscribe to incoming token transfers
623
+ * @returns Unsubscribe function
624
+ */
625
+ onTokenTransfer(handler: TokenTransferHandler): () => void;
626
+ /**
627
+ * Resolve nametag to public key
628
+ */
629
+ resolveNametag?(nametag: string): Promise<string | null>;
630
+ /**
631
+ * Resolve nametag to full address information
632
+ * Returns transportPubkey, chainPubkey, l1Address, directAddress, proxyAddress
633
+ */
634
+ resolveNametagInfo?(nametag: string): Promise<NametagInfo | null>;
635
+ /**
636
+ * Recover nametag for current identity by decrypting stored encrypted nametag
637
+ * Used after wallet import to recover associated nametag
638
+ * @returns Decrypted nametag or null if none found
639
+ */
640
+ recoverNametag?(): Promise<string | null>;
641
+ /**
642
+ * Register a nametag for this identity
643
+ * @param nametag - Nametag to register
644
+ * @param chainPubkey - 33-byte compressed secp256k1 public key (for L1/L3)
645
+ * @param directAddress - L3 DIRECT address (DIRECT://...)
646
+ * @returns true if successful, false if already taken
647
+ */
648
+ registerNametag?(nametag: string, chainPubkey: string, directAddress: string): Promise<boolean>;
649
+ /**
650
+ * Publish nametag binding
651
+ */
652
+ publishNametag?(nametag: string, address: string): Promise<void>;
653
+ /**
654
+ * Subscribe to broadcast messages (global/channel)
655
+ */
656
+ subscribeToBroadcast?(tags: string[], handler: BroadcastHandler): () => void;
657
+ /**
658
+ * Publish broadcast message
659
+ */
660
+ publishBroadcast?(content: string, tags?: string[]): Promise<string>;
661
+ /**
662
+ * Send payment request to a recipient
663
+ * @param recipientTransportPubkey - Transport-specific pubkey for messaging
664
+ * @returns Event ID
665
+ */
666
+ sendPaymentRequest?(recipientTransportPubkey: string, request: PaymentRequestPayload): Promise<string>;
667
+ /**
668
+ * Subscribe to incoming payment requests
669
+ * @returns Unsubscribe function
670
+ */
671
+ onPaymentRequest?(handler: PaymentRequestHandler): () => void;
672
+ /**
673
+ * Send response to a payment request
674
+ * @param recipientTransportPubkey - Transport-specific pubkey for messaging
675
+ * @returns Event ID
676
+ */
677
+ sendPaymentRequestResponse?(recipientTransportPubkey: string, response: PaymentRequestResponsePayload): Promise<string>;
678
+ /**
679
+ * Subscribe to incoming payment request responses
680
+ * @returns Unsubscribe function
681
+ */
682
+ onPaymentRequestResponse?(handler: PaymentRequestResponseHandler): () => void;
683
+ /**
684
+ * Get list of configured relay URLs
685
+ */
686
+ getRelays?(): string[];
687
+ /**
688
+ * Get list of currently connected relay URLs
689
+ */
690
+ getConnectedRelays?(): string[];
691
+ /**
692
+ * Add a relay dynamically
693
+ * @returns true if added successfully
694
+ */
695
+ addRelay?(relayUrl: string): Promise<boolean>;
696
+ /**
697
+ * Remove a relay dynamically
698
+ * @returns true if removed successfully
699
+ */
700
+ removeRelay?(relayUrl: string): Promise<boolean>;
701
+ /**
702
+ * Check if a relay is configured
703
+ */
704
+ hasRelay?(relayUrl: string): boolean;
705
+ /**
706
+ * Check if a relay is currently connected
707
+ */
708
+ isRelayConnected?(relayUrl: string): boolean;
709
+ }
710
+ interface IncomingMessage {
711
+ id: string;
712
+ /** Transport-specific pubkey of sender */
713
+ senderTransportPubkey: string;
714
+ /** Sender's nametag (if known from NIP-17 unwrap) */
715
+ senderNametag?: string;
716
+ content: string;
717
+ timestamp: number;
718
+ encrypted: boolean;
719
+ }
720
+ type MessageHandler = (message: IncomingMessage) => void;
721
+ interface TokenTransferPayload {
722
+ /** Serialized token data */
723
+ token: string;
724
+ /** Inclusion proof */
725
+ proof: unknown;
726
+ /** Optional memo */
727
+ memo?: string;
728
+ /** Sender info */
729
+ sender?: {
730
+ /** Transport-specific pubkey */
731
+ transportPubkey: string;
732
+ nametag?: string;
733
+ };
734
+ }
735
+ interface IncomingTokenTransfer {
736
+ id: string;
737
+ /** Transport-specific pubkey of sender */
738
+ senderTransportPubkey: string;
739
+ payload: TokenTransferPayload;
740
+ timestamp: number;
741
+ }
742
+ type TokenTransferHandler = (transfer: IncomingTokenTransfer) => void;
743
+ interface PaymentRequestPayload {
744
+ /** Amount requested (in smallest units) */
745
+ amount: string | bigint;
746
+ /** Coin/token type ID */
747
+ coinId: string;
748
+ /** Message/memo for recipient */
749
+ message?: string;
750
+ /** Recipient's nametag (who should pay) */
751
+ recipientNametag?: string;
752
+ /** Custom metadata */
753
+ metadata?: Record<string, unknown>;
754
+ }
755
+ interface IncomingPaymentRequest {
756
+ /** Event ID */
757
+ id: string;
758
+ /** Transport-specific pubkey of sender */
759
+ senderTransportPubkey: string;
760
+ /** Parsed request data */
761
+ request: {
762
+ requestId: string;
763
+ amount: string;
764
+ coinId: string;
765
+ message?: string;
766
+ recipientNametag?: string;
767
+ metadata?: Record<string, unknown>;
768
+ };
769
+ /** Timestamp */
770
+ timestamp: number;
771
+ }
772
+ type PaymentRequestHandler = (request: IncomingPaymentRequest) => void;
773
+ type PaymentRequestResponseType = 'accepted' | 'rejected' | 'paid';
774
+ interface PaymentRequestResponsePayload {
775
+ /** Original request ID */
776
+ requestId: string;
777
+ /** Response type */
778
+ responseType: PaymentRequestResponseType;
779
+ /** Optional message */
780
+ message?: string;
781
+ /** Transfer ID (if paid) */
782
+ transferId?: string;
783
+ }
784
+ interface IncomingPaymentRequestResponse {
785
+ /** Event ID */
786
+ id: string;
787
+ /** Transport-specific pubkey of responder */
788
+ responderTransportPubkey: string;
789
+ /** Parsed response data */
790
+ response: {
791
+ requestId: string;
792
+ responseType: PaymentRequestResponseType;
793
+ message?: string;
794
+ transferId?: string;
795
+ };
796
+ /** Timestamp */
797
+ timestamp: number;
798
+ }
799
+ type PaymentRequestResponseHandler = (response: IncomingPaymentRequestResponse) => void;
800
+ interface IncomingBroadcast {
801
+ id: string;
802
+ /** Transport-specific pubkey of author */
803
+ authorTransportPubkey: string;
804
+ content: string;
805
+ tags: string[];
806
+ timestamp: number;
807
+ }
808
+ type BroadcastHandler = (broadcast: IncomingBroadcast) => void;
809
+ /**
810
+ * Full nametag address information
811
+ * Used for resolving nametag to all address formats
812
+ */
813
+ interface NametagInfo {
814
+ /** Nametag name (without @) */
815
+ nametag: string;
816
+ /** Transport-specific pubkey (for messaging/encryption) */
817
+ transportPubkey: string;
818
+ /** 33-byte compressed secp256k1 public key (for L3 chain) */
819
+ chainPubkey: string;
820
+ /** L1 address (alpha1...) */
821
+ l1Address: string;
822
+ /** L3 DIRECT address (DIRECT://...) */
823
+ directAddress: string;
824
+ /** L3 PROXY address derived from nametag hash (PROXY:...) */
825
+ proxyAddress: string;
826
+ /** Event timestamp */
827
+ timestamp: number;
828
+ }
829
+
587
830
  /**
588
831
  * L1 Payments Sub-Module
589
832
  *
@@ -653,6 +896,8 @@ interface L1PaymentsModuleDependencies {
653
896
  identity: FullIdentity;
654
897
  chainCode?: string;
655
898
  addresses?: string[];
899
+ /** Transport provider for nametag resolution (optional) */
900
+ transport?: TransportProvider;
656
901
  }
657
902
  /**
658
903
  * L1 Payments Module - Full Implementation
@@ -667,9 +912,23 @@ declare class L1PaymentsModule {
667
912
  private _chainCode?;
668
913
  private _addresses;
669
914
  private _wallet?;
915
+ private _transport?;
670
916
  constructor(config?: L1PaymentsModuleConfig);
671
917
  initialize(deps: L1PaymentsModuleDependencies): Promise<void>;
672
918
  destroy(): void;
919
+ /**
920
+ * Check if a string looks like an L1 address (alpha1... or alphat1...)
921
+ */
922
+ private isL1Address;
923
+ /**
924
+ * Resolve recipient to L1 address
925
+ * Supports: L1 address (alpha1...), nametag (with or without @)
926
+ */
927
+ private resolveL1Address;
928
+ /**
929
+ * Resolve nametag to L1 address using transport provider
930
+ */
931
+ private resolveNametagToL1Address;
673
932
  send(request: L1SendRequest): Promise<L1SendResult>;
674
933
  getBalance(): Promise<L1Balance>;
675
934
  getUtxos(): Promise<L1Utxo[]>;
@@ -878,201 +1137,6 @@ interface TxfInvalidEntry {
878
1137
  detectedAt: number;
879
1138
  }
880
1139
 
881
- /**
882
- * Transport Provider Interface
883
- * Platform-independent P2P messaging abstraction
884
- */
885
-
886
- /**
887
- * P2P messaging transport provider
888
- */
889
- interface TransportProvider extends BaseProvider {
890
- /**
891
- * Set identity for signing/encryption
892
- */
893
- setIdentity(identity: FullIdentity): void;
894
- /**
895
- * Send encrypted direct message
896
- * @returns Event ID
897
- */
898
- sendMessage(recipientPubkey: string, content: string): Promise<string>;
899
- /**
900
- * Subscribe to incoming direct messages
901
- * @returns Unsubscribe function
902
- */
903
- onMessage(handler: MessageHandler): () => void;
904
- /**
905
- * Send token transfer payload
906
- * @returns Event ID
907
- */
908
- sendTokenTransfer(recipientPubkey: string, payload: TokenTransferPayload): Promise<string>;
909
- /**
910
- * Subscribe to incoming token transfers
911
- * @returns Unsubscribe function
912
- */
913
- onTokenTransfer(handler: TokenTransferHandler): () => void;
914
- /**
915
- * Resolve nametag to public key
916
- */
917
- resolveNametag?(nametag: string): Promise<string | null>;
918
- /**
919
- * Register a nametag for this identity
920
- * @returns true if successful, false if already taken
921
- */
922
- registerNametag?(nametag: string, publicKey: string): Promise<boolean>;
923
- /**
924
- * Publish nametag binding
925
- */
926
- publishNametag?(nametag: string, address: string): Promise<void>;
927
- /**
928
- * Subscribe to broadcast messages (global/channel)
929
- */
930
- subscribeToBroadcast?(tags: string[], handler: BroadcastHandler): () => void;
931
- /**
932
- * Publish broadcast message
933
- */
934
- publishBroadcast?(content: string, tags?: string[]): Promise<string>;
935
- /**
936
- * Send payment request to a recipient
937
- * @returns Event ID
938
- */
939
- sendPaymentRequest?(recipientPubkey: string, request: PaymentRequestPayload): Promise<string>;
940
- /**
941
- * Subscribe to incoming payment requests
942
- * @returns Unsubscribe function
943
- */
944
- onPaymentRequest?(handler: PaymentRequestHandler): () => void;
945
- /**
946
- * Send response to a payment request
947
- * @returns Event ID
948
- */
949
- sendPaymentRequestResponse?(recipientPubkey: string, response: PaymentRequestResponsePayload): Promise<string>;
950
- /**
951
- * Subscribe to incoming payment request responses
952
- * @returns Unsubscribe function
953
- */
954
- onPaymentRequestResponse?(handler: PaymentRequestResponseHandler): () => void;
955
- /**
956
- * Get list of configured relay URLs
957
- */
958
- getRelays?(): string[];
959
- /**
960
- * Get list of currently connected relay URLs
961
- */
962
- getConnectedRelays?(): string[];
963
- /**
964
- * Add a relay dynamically
965
- * @returns true if added successfully
966
- */
967
- addRelay?(relayUrl: string): Promise<boolean>;
968
- /**
969
- * Remove a relay dynamically
970
- * @returns true if removed successfully
971
- */
972
- removeRelay?(relayUrl: string): Promise<boolean>;
973
- /**
974
- * Check if a relay is configured
975
- */
976
- hasRelay?(relayUrl: string): boolean;
977
- /**
978
- * Check if a relay is currently connected
979
- */
980
- isRelayConnected?(relayUrl: string): boolean;
981
- }
982
- interface IncomingMessage {
983
- id: string;
984
- senderPubkey: string;
985
- content: string;
986
- timestamp: number;
987
- encrypted: boolean;
988
- }
989
- type MessageHandler = (message: IncomingMessage) => void;
990
- interface TokenTransferPayload {
991
- /** Serialized token data */
992
- token: string;
993
- /** Inclusion proof */
994
- proof: unknown;
995
- /** Optional memo */
996
- memo?: string;
997
- /** Sender info */
998
- sender?: {
999
- pubkey: string;
1000
- nametag?: string;
1001
- };
1002
- }
1003
- interface IncomingTokenTransfer {
1004
- id: string;
1005
- senderPubkey: string;
1006
- payload: TokenTransferPayload;
1007
- timestamp: number;
1008
- }
1009
- type TokenTransferHandler = (transfer: IncomingTokenTransfer) => void;
1010
- interface PaymentRequestPayload {
1011
- /** Amount requested (in smallest units) */
1012
- amount: string | bigint;
1013
- /** Coin/token type ID */
1014
- coinId: string;
1015
- /** Message/memo for recipient */
1016
- message?: string;
1017
- /** Recipient's nametag (who should pay) */
1018
- recipientNametag?: string;
1019
- /** Custom metadata */
1020
- metadata?: Record<string, unknown>;
1021
- }
1022
- interface IncomingPaymentRequest {
1023
- /** Event ID */
1024
- id: string;
1025
- /** Sender's public key */
1026
- senderPubkey: string;
1027
- /** Parsed request data */
1028
- request: {
1029
- requestId: string;
1030
- amount: string;
1031
- coinId: string;
1032
- message?: string;
1033
- recipientNametag?: string;
1034
- metadata?: Record<string, unknown>;
1035
- };
1036
- /** Timestamp */
1037
- timestamp: number;
1038
- }
1039
- type PaymentRequestHandler = (request: IncomingPaymentRequest) => void;
1040
- type PaymentRequestResponseType = 'accepted' | 'rejected' | 'paid';
1041
- interface PaymentRequestResponsePayload {
1042
- /** Original request ID */
1043
- requestId: string;
1044
- /** Response type */
1045
- responseType: PaymentRequestResponseType;
1046
- /** Optional message */
1047
- message?: string;
1048
- /** Transfer ID (if paid) */
1049
- transferId?: string;
1050
- }
1051
- interface IncomingPaymentRequestResponse {
1052
- /** Event ID */
1053
- id: string;
1054
- /** Responder's public key */
1055
- responderPubkey: string;
1056
- /** Parsed response data */
1057
- response: {
1058
- requestId: string;
1059
- responseType: PaymentRequestResponseType;
1060
- message?: string;
1061
- transferId?: string;
1062
- };
1063
- /** Timestamp */
1064
- timestamp: number;
1065
- }
1066
- type PaymentRequestResponseHandler = (response: IncomingPaymentRequestResponse) => void;
1067
- interface IncomingBroadcast {
1068
- id: string;
1069
- authorPubkey: string;
1070
- content: string;
1071
- tags: string[];
1072
- timestamp: number;
1073
- }
1074
- type BroadcastHandler = (broadcast: IncomingBroadcast) => void;
1075
-
1076
1140
  /**
1077
1141
  * Oracle Provider Interface
1078
1142
  * Platform-independent Unicity oracle abstraction
@@ -1554,6 +1618,15 @@ declare class PaymentsModule {
1554
1618
  * Get pending transfers
1555
1619
  */
1556
1620
  getPendingTransfers(): TransferResult[];
1621
+ /**
1622
+ * Detect if a string is an L3 address (not a nametag)
1623
+ * Returns true for: hex pubkeys (64+ chars), PROXY:, DIRECT: prefixed addresses
1624
+ */
1625
+ private isL3Address;
1626
+ /**
1627
+ * Resolve recipient to Nostr pubkey for messaging
1628
+ * Supports: nametag (with or without @), hex pubkey
1629
+ */
1557
1630
  private resolveRecipient;
1558
1631
  /**
1559
1632
  * Create SDK TransferCommitment for a token transfer
@@ -1564,7 +1637,17 @@ declare class PaymentsModule {
1564
1637
  */
1565
1638
  private createSigningService;
1566
1639
  /**
1567
- * Resolve recipient to IAddress
1640
+ * Create DirectAddress from a public key using UnmaskedPredicateReference
1641
+ */
1642
+ private createDirectAddressFromPubkey;
1643
+ /**
1644
+ * Resolve nametag to 33-byte compressed public key using resolveNametagInfo
1645
+ * Returns null if nametag not found or publicKey not available
1646
+ */
1647
+ private resolveNametagToPublicKey;
1648
+ /**
1649
+ * Resolve recipient to IAddress for L3 transfers
1650
+ * Supports: nametag (with or without @), PROXY:, DIRECT:, hex pubkey
1568
1651
  */
1569
1652
  private resolveRecipientAddress;
1570
1653
  private handleIncomingTransfer;
@@ -2209,6 +2292,13 @@ declare class Sphere {
2209
2292
  * Check if nametag is registered
2210
2293
  */
2211
2294
  hasNametag(): boolean;
2295
+ /**
2296
+ * Get the PROXY address for the current nametag
2297
+ * PROXY addresses are derived from the nametag hash and require
2298
+ * the nametag token to claim funds sent to them
2299
+ * @returns PROXY address string or undefined if no nametag
2300
+ */
2301
+ getProxyAddress(): string | undefined;
2212
2302
  /**
2213
2303
  * Register a nametag for the current active address
2214
2304
  * Each address can have its own independent nametag
@@ -2266,6 +2356,12 @@ declare class Sphere {
2266
2356
  * If local nametag exists but not registered on Nostr, re-register it
2267
2357
  */
2268
2358
  private syncNametagWithNostr;
2359
+ /**
2360
+ * Recover nametag from Nostr after wallet import
2361
+ * Searches for encrypted nametag events authored by this wallet's pubkey
2362
+ * and decrypts them to restore the nametag association
2363
+ */
2364
+ private recoverNametagFromNostr;
2269
2365
  /**
2270
2366
  * Validate nametag format
2271
2367
  */