@toon-protocol/client 0.8.0 → 0.9.1
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.
- package/LICENSE +190 -0
- package/dist/chunk-5WRI5ZAA.js +31 -0
- package/dist/chunk-5WRI5ZAA.js.map +1 -0
- package/dist/index.d.ts +514 -78
- package/dist/index.js +2080 -99
- package/dist/index.js.map +1 -1
- package/dist/mina-signer-J7GFWOGO.js +6317 -0
- package/dist/mina-signer-J7GFWOGO.js.map +1 -0
- package/package.json +16 -17
package/dist/index.d.ts
CHANGED
|
@@ -210,6 +210,7 @@ declare class ToonClient {
|
|
|
210
210
|
private state;
|
|
211
211
|
private readonly evmSigner?;
|
|
212
212
|
private channelManager?;
|
|
213
|
+
private readonly peerNegotiations;
|
|
213
214
|
/**
|
|
214
215
|
* Creates a new ToonClient instance.
|
|
215
216
|
*
|
|
@@ -285,6 +286,12 @@ declare class ToonClient {
|
|
|
285
286
|
* Gets the cumulative transferred amount for a tracked channel.
|
|
286
287
|
*/
|
|
287
288
|
getChannelCumulativeAmount(channelId: string): bigint;
|
|
289
|
+
/**
|
|
290
|
+
* Resolves an ILP destination address to a peer ID.
|
|
291
|
+
* Convention: destination "g.toon.peer1" → peerId "peer1" (last segment).
|
|
292
|
+
* Falls back to first known peer if no match.
|
|
293
|
+
*/
|
|
294
|
+
private resolvePeerId;
|
|
288
295
|
/**
|
|
289
296
|
* Extracts chain context (chainId + tokenNetworkAddress) from a chain key like 'evm:base:421614'.
|
|
290
297
|
*/
|
|
@@ -664,6 +671,128 @@ declare class HttpConnectorAdmin implements ConnectorAdminClient {
|
|
|
664
671
|
private handleErrorResponse;
|
|
665
672
|
}
|
|
666
673
|
|
|
674
|
+
interface BtpRuntimeClientConfig {
|
|
675
|
+
btpUrl: string;
|
|
676
|
+
peerId: string;
|
|
677
|
+
authToken: string;
|
|
678
|
+
/** Max reconnection attempts on send failure (default: 3) */
|
|
679
|
+
maxRetries?: number;
|
|
680
|
+
/** Delay between reconnection attempts in ms (default: 1000) */
|
|
681
|
+
retryDelay?: number;
|
|
682
|
+
}
|
|
683
|
+
/**
|
|
684
|
+
* BTP transport implementing IlpClient.
|
|
685
|
+
* Uses IsomorphicBtpClient (browser-native, no Node.js dependencies).
|
|
686
|
+
*/
|
|
687
|
+
declare class BtpRuntimeClient implements IlpClient {
|
|
688
|
+
private btpClient;
|
|
689
|
+
private readonly config;
|
|
690
|
+
private _isConnected;
|
|
691
|
+
constructor(config: BtpRuntimeClientConfig);
|
|
692
|
+
/**
|
|
693
|
+
* Connects to the BTP peer via WebSocket.
|
|
694
|
+
*/
|
|
695
|
+
connect(): Promise<void>;
|
|
696
|
+
/**
|
|
697
|
+
* Attempts to reconnect by creating a fresh client and connecting.
|
|
698
|
+
*/
|
|
699
|
+
reconnect(): Promise<void>;
|
|
700
|
+
/**
|
|
701
|
+
* Disconnects from the BTP peer.
|
|
702
|
+
*/
|
|
703
|
+
disconnect(): Promise<void>;
|
|
704
|
+
get isConnected(): boolean;
|
|
705
|
+
/**
|
|
706
|
+
* Sends an ILP packet via BTP with auto-reconnect on connection errors.
|
|
707
|
+
* Satisfies IlpClient interface.
|
|
708
|
+
*/
|
|
709
|
+
sendIlpPacket(params: {
|
|
710
|
+
destination: string;
|
|
711
|
+
amount: string;
|
|
712
|
+
data: string;
|
|
713
|
+
timeout?: number;
|
|
714
|
+
}): Promise<IlpSendResult>;
|
|
715
|
+
/**
|
|
716
|
+
* Sends a balance proof claim via BTP protocol data, then sends an ILP packet.
|
|
717
|
+
* Auto-reconnects on connection errors.
|
|
718
|
+
*/
|
|
719
|
+
sendIlpPacketWithClaim(params: {
|
|
720
|
+
destination: string;
|
|
721
|
+
amount: string;
|
|
722
|
+
data: string;
|
|
723
|
+
timeout?: number;
|
|
724
|
+
}, claim: Record<string, unknown>): Promise<IlpSendResult>;
|
|
725
|
+
/**
|
|
726
|
+
* Single-attempt ILP packet send. Reconnects if not connected.
|
|
727
|
+
*/
|
|
728
|
+
private _sendIlpPacketOnce;
|
|
729
|
+
/**
|
|
730
|
+
* Single-attempt claim + ILP packet send. Reconnects if not connected.
|
|
731
|
+
*/
|
|
732
|
+
private _sendIlpPacketWithClaimOnce;
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
/**
|
|
736
|
+
* Chain-specific metadata (discriminated union).
|
|
737
|
+
*/
|
|
738
|
+
type ChainMetadata = {
|
|
739
|
+
chainType: 'evm';
|
|
740
|
+
chainId: number;
|
|
741
|
+
tokenNetworkAddress: string;
|
|
742
|
+
tokenAddress?: string;
|
|
743
|
+
} | {
|
|
744
|
+
chainType: 'solana';
|
|
745
|
+
programId: string;
|
|
746
|
+
tokenMint?: string;
|
|
747
|
+
} | {
|
|
748
|
+
chainType: 'mina';
|
|
749
|
+
zkAppAddress: string;
|
|
750
|
+
tokenId?: string;
|
|
751
|
+
};
|
|
752
|
+
/**
|
|
753
|
+
* Chain-agnostic signing interface for balance proofs.
|
|
754
|
+
*/
|
|
755
|
+
interface ChainSigner {
|
|
756
|
+
readonly chainType: 'evm' | 'solana' | 'mina';
|
|
757
|
+
readonly signerIdentifier: string;
|
|
758
|
+
signBalanceProof(params: {
|
|
759
|
+
channelId: string;
|
|
760
|
+
nonce: number;
|
|
761
|
+
transferredAmount: bigint;
|
|
762
|
+
lockedAmount: bigint;
|
|
763
|
+
locksRoot: string;
|
|
764
|
+
metadata: ChainMetadata;
|
|
765
|
+
}): Promise<SignedBalanceProof>;
|
|
766
|
+
buildClaimMessage(proof: SignedBalanceProof, senderId: string): ClaimMessage;
|
|
767
|
+
}
|
|
768
|
+
type ClaimMessage = EVMClaimMessage | SolanaClaimMessage | MinaClaimMessage;
|
|
769
|
+
interface SolanaClaimMessage {
|
|
770
|
+
version: '1.0';
|
|
771
|
+
blockchain: 'solana';
|
|
772
|
+
messageId: string;
|
|
773
|
+
timestamp: string;
|
|
774
|
+
senderId: string;
|
|
775
|
+
channelId: string;
|
|
776
|
+
nonce: number;
|
|
777
|
+
transferredAmount: string;
|
|
778
|
+
signature: string;
|
|
779
|
+
signerAddress: string;
|
|
780
|
+
programId: string;
|
|
781
|
+
}
|
|
782
|
+
interface MinaClaimMessage {
|
|
783
|
+
version: '1.0';
|
|
784
|
+
blockchain: 'mina';
|
|
785
|
+
messageId: string;
|
|
786
|
+
timestamp: string;
|
|
787
|
+
senderId: string;
|
|
788
|
+
channelId: string;
|
|
789
|
+
nonce: number;
|
|
790
|
+
transferredAmount: string;
|
|
791
|
+
commitment: string;
|
|
792
|
+
signerAddress: string;
|
|
793
|
+
zkAppAddress: string;
|
|
794
|
+
}
|
|
795
|
+
|
|
667
796
|
/**
|
|
668
797
|
* EVM claim message for BTP protocol data.
|
|
669
798
|
* Matches @toon-protocol/connector's EVMClaimMessage interface.
|
|
@@ -698,6 +827,7 @@ interface EVMClaimMessage {
|
|
|
698
827
|
* Encapsulates the private key — no getPrivateKey() method is exposed.
|
|
699
828
|
*/
|
|
700
829
|
declare class EvmSigner {
|
|
830
|
+
readonly chainType: "evm";
|
|
701
831
|
private readonly _account;
|
|
702
832
|
/**
|
|
703
833
|
* @param privateKey - EVM private key as hex string (with or without 0x prefix) or Uint8Array
|
|
@@ -705,6 +835,8 @@ declare class EvmSigner {
|
|
|
705
835
|
constructor(privateKey: string | Uint8Array);
|
|
706
836
|
/** Derived 0x EVM address */
|
|
707
837
|
get address(): string;
|
|
838
|
+
/** ChainSigner identifier — EVM address */
|
|
839
|
+
get signerIdentifier(): string;
|
|
708
840
|
/** Viem PrivateKeyAccount — usable with walletClient for on-chain transactions */
|
|
709
841
|
get account(): PrivateKeyAccount;
|
|
710
842
|
/**
|
|
@@ -729,85 +861,70 @@ declare class EvmSigner {
|
|
|
729
861
|
static buildClaimMessage(proof: SignedBalanceProof, senderId: string): EVMClaimMessage;
|
|
730
862
|
}
|
|
731
863
|
|
|
732
|
-
/**
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
864
|
+
/**
|
|
865
|
+
* Solana signer for Ed25519 balance proofs.
|
|
866
|
+
*
|
|
867
|
+
* Signs channel state using Ed25519 (raw, not EIP-712).
|
|
868
|
+
* Dynamically imports @noble/curves to avoid missing-dep errors for non-Solana users.
|
|
869
|
+
*/
|
|
870
|
+
declare class SolanaSigner implements ChainSigner {
|
|
871
|
+
readonly chainType: "solana";
|
|
872
|
+
private readonly privateKey;
|
|
873
|
+
private publicKey?;
|
|
874
|
+
private pubkeyBase58Cache?;
|
|
875
|
+
constructor(privateKey: Uint8Array);
|
|
876
|
+
private ensurePublicKey;
|
|
877
|
+
get signerIdentifier(): string;
|
|
878
|
+
signBalanceProof(params: {
|
|
879
|
+
channelId: string;
|
|
880
|
+
nonce: number;
|
|
881
|
+
transferredAmount: bigint;
|
|
882
|
+
lockedAmount: bigint;
|
|
883
|
+
locksRoot: string;
|
|
884
|
+
metadata: ChainMetadata;
|
|
885
|
+
}): Promise<SignedBalanceProof>;
|
|
886
|
+
buildClaimMessage(proof: SignedBalanceProof, senderId: string): ClaimMessage;
|
|
753
887
|
}
|
|
888
|
+
|
|
754
889
|
/**
|
|
755
|
-
*
|
|
756
|
-
*
|
|
890
|
+
* Mina signer for Poseidon commitment balance proofs.
|
|
891
|
+
*
|
|
892
|
+
* Dynamically imports o1js to avoid pulling 50MB into the client bundle
|
|
893
|
+
* for non-Mina users.
|
|
757
894
|
*/
|
|
758
|
-
declare class
|
|
759
|
-
|
|
760
|
-
private readonly
|
|
761
|
-
private
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
*/
|
|
775
|
-
disconnect(): Promise<void>;
|
|
776
|
-
get isConnected(): boolean;
|
|
777
|
-
/**
|
|
778
|
-
* Sends an ILP packet via BTP with auto-reconnect on connection errors.
|
|
779
|
-
* Satisfies IlpClient interface.
|
|
780
|
-
*/
|
|
781
|
-
sendIlpPacket(params: {
|
|
782
|
-
destination: string;
|
|
783
|
-
amount: string;
|
|
784
|
-
data: string;
|
|
785
|
-
timeout?: number;
|
|
786
|
-
}): Promise<IlpSendResult>;
|
|
787
|
-
/**
|
|
788
|
-
* Sends a balance proof claim via BTP protocol data, then sends an ILP packet.
|
|
789
|
-
* Auto-reconnects on connection errors.
|
|
790
|
-
*/
|
|
791
|
-
sendIlpPacketWithClaim(params: {
|
|
792
|
-
destination: string;
|
|
793
|
-
amount: string;
|
|
794
|
-
data: string;
|
|
795
|
-
timeout?: number;
|
|
796
|
-
}, claim: EVMClaimMessage): Promise<IlpSendResult>;
|
|
797
|
-
/**
|
|
798
|
-
* Single-attempt ILP packet send. Reconnects if not connected.
|
|
799
|
-
*/
|
|
800
|
-
private _sendIlpPacketOnce;
|
|
801
|
-
/**
|
|
802
|
-
* Single-attempt claim + ILP packet send. Reconnects if not connected.
|
|
803
|
-
* Embeds the claim in the same BTP message as the ILP PREPARE packet.
|
|
804
|
-
*/
|
|
805
|
-
private _sendIlpPacketWithClaimOnce;
|
|
895
|
+
declare class MinaSigner implements ChainSigner {
|
|
896
|
+
readonly chainType: "mina";
|
|
897
|
+
private readonly privateKeyBase58;
|
|
898
|
+
private publicKeyBase58;
|
|
899
|
+
constructor(privateKeyBase58: string);
|
|
900
|
+
get signerIdentifier(): string;
|
|
901
|
+
private ensurePublicKey;
|
|
902
|
+
signBalanceProof(params: {
|
|
903
|
+
channelId: string;
|
|
904
|
+
nonce: number;
|
|
905
|
+
transferredAmount: bigint;
|
|
906
|
+
lockedAmount: bigint;
|
|
907
|
+
locksRoot: string;
|
|
908
|
+
metadata: ChainMetadata;
|
|
909
|
+
}): Promise<SignedBalanceProof>;
|
|
910
|
+
buildClaimMessage(proof: SignedBalanceProof, senderId: string): ClaimMessage;
|
|
806
911
|
}
|
|
807
912
|
|
|
913
|
+
interface SolanaChannelConfig {
|
|
914
|
+
rpcUrl: string;
|
|
915
|
+
keypair: Uint8Array;
|
|
916
|
+
programId: string;
|
|
917
|
+
}
|
|
918
|
+
interface MinaChannelConfig {
|
|
919
|
+
graphqlUrl: string;
|
|
920
|
+
privateKey: string;
|
|
921
|
+
zkAppAddress: string;
|
|
922
|
+
}
|
|
808
923
|
interface OnChainChannelClientConfig {
|
|
809
924
|
evmSigner: EvmSigner;
|
|
810
925
|
chainRpcUrls: Record<string, string>;
|
|
926
|
+
solanaConfig?: SolanaChannelConfig;
|
|
927
|
+
minaConfig?: MinaChannelConfig;
|
|
811
928
|
}
|
|
812
929
|
/**
|
|
813
930
|
* Implements ConnectorChannelClient using viem for direct on-chain
|
|
@@ -818,6 +935,8 @@ interface OnChainChannelClientConfig {
|
|
|
818
935
|
declare class OnChainChannelClient implements ConnectorChannelClient {
|
|
819
936
|
private readonly evmSigner;
|
|
820
937
|
private readonly chainRpcUrls;
|
|
938
|
+
private readonly solanaConfig?;
|
|
939
|
+
private readonly minaConfig?;
|
|
821
940
|
private readonly channelContext;
|
|
822
941
|
constructor(config: OnChainChannelClientConfig);
|
|
823
942
|
/**
|
|
@@ -838,6 +957,24 @@ declare class OnChainChannelClient implements ConnectorChannelClient {
|
|
|
838
957
|
* 4. Deposit initial funds if specified
|
|
839
958
|
*/
|
|
840
959
|
openChannel(params: OpenChannelParams): Promise<OpenChannelResult>;
|
|
960
|
+
/**
|
|
961
|
+
* Opens a Solana payment channel (PDA creation).
|
|
962
|
+
*/
|
|
963
|
+
private openSolanaChannel;
|
|
964
|
+
/**
|
|
965
|
+
* Opens a Mina payment channel (zkApp state transition).
|
|
966
|
+
* Dynamically imports o1js to avoid bundle bloat.
|
|
967
|
+
*/
|
|
968
|
+
private openMinaChannel;
|
|
969
|
+
/**
|
|
970
|
+
* Opens an EVM payment channel on-chain.
|
|
971
|
+
*
|
|
972
|
+
* 1. Approve token spend if needed
|
|
973
|
+
* 2. Call TokenNetwork.openChannel()
|
|
974
|
+
* 3. Extract channelId from ChannelOpened event
|
|
975
|
+
* 4. Deposit initial funds if specified
|
|
976
|
+
*/
|
|
977
|
+
private openEvmChannel;
|
|
841
978
|
/**
|
|
842
979
|
* Gets the current state of a payment channel from on-chain data.
|
|
843
980
|
*/
|
|
@@ -858,27 +995,70 @@ interface ChannelStore {
|
|
|
858
995
|
delete(channelId: string): void;
|
|
859
996
|
}
|
|
860
997
|
|
|
998
|
+
interface ChannelManagerConfig {
|
|
999
|
+
initialDeposit?: string;
|
|
1000
|
+
settlementTimeout?: number;
|
|
1001
|
+
}
|
|
1002
|
+
interface PeerNegotiation {
|
|
1003
|
+
chain: string;
|
|
1004
|
+
chainType: string;
|
|
1005
|
+
chainId: number | string;
|
|
1006
|
+
settlementAddress: string;
|
|
1007
|
+
tokenAddress?: string;
|
|
1008
|
+
tokenNetwork?: string;
|
|
1009
|
+
initialDeposit?: string;
|
|
1010
|
+
settlementTimeout?: number;
|
|
1011
|
+
}
|
|
861
1012
|
/**
|
|
862
|
-
* Local nonce tracking and
|
|
1013
|
+
* Local nonce tracking, multi-chain signing, and lazy channel opening.
|
|
863
1014
|
*
|
|
864
|
-
*
|
|
865
|
-
*
|
|
1015
|
+
* Supports multiple ChainSigner implementations (EVM, Solana, Mina).
|
|
1016
|
+
* The ensureChannel() method provides idempotent lazy channel opening.
|
|
866
1017
|
*/
|
|
867
1018
|
declare class ChannelManager {
|
|
868
|
-
private readonly evmSigner;
|
|
869
1019
|
private readonly channels;
|
|
1020
|
+
private readonly chainSigners;
|
|
1021
|
+
private readonly peerChannels;
|
|
1022
|
+
private readonly pendingOpens;
|
|
870
1023
|
private readonly store?;
|
|
871
|
-
|
|
1024
|
+
private readonly defaultInitialDeposit;
|
|
1025
|
+
private readonly defaultSettlementTimeout;
|
|
1026
|
+
private channelClient?;
|
|
1027
|
+
private readonly evmSigner?;
|
|
1028
|
+
constructor(evmSigner?: EvmSigner, store?: ChannelStore, config?: ChannelManagerConfig);
|
|
1029
|
+
/**
|
|
1030
|
+
* Register a chain-specific signer.
|
|
1031
|
+
*/
|
|
1032
|
+
registerChainSigner(chainType: string, signer: ChainSigner): void;
|
|
1033
|
+
/**
|
|
1034
|
+
* Set the on-chain channel client for lazy channel opening.
|
|
1035
|
+
*/
|
|
1036
|
+
setChannelClient(client: ConnectorChannelClient): void;
|
|
1037
|
+
/**
|
|
1038
|
+
* Get the signer for a tracked channel's chain type.
|
|
1039
|
+
* For EVM, returns an adapter wrapping the EvmSigner.
|
|
1040
|
+
*/
|
|
1041
|
+
getSignerForChannel(channelId: string): ChainSigner;
|
|
1042
|
+
/**
|
|
1043
|
+
* Lazily open a channel for a peer. Idempotent — returns existing channel
|
|
1044
|
+
* if already open. Deduplicates concurrent opens for the same peer.
|
|
1045
|
+
*/
|
|
1046
|
+
ensureChannel(peerId: string, negotiation: PeerNegotiation): Promise<string>;
|
|
1047
|
+
/**
|
|
1048
|
+
* Get channel ID for a peer (if any).
|
|
1049
|
+
*/
|
|
1050
|
+
getChannelForPeer(peerId: string): string | undefined;
|
|
872
1051
|
/**
|
|
873
1052
|
* Start tracking a channel.
|
|
874
1053
|
* Called after bootstrap returns a channelId.
|
|
875
1054
|
*
|
|
876
1055
|
* @param channelId - Payment channel identifier
|
|
877
|
-
* @param chainContext - Chain context for
|
|
1056
|
+
* @param chainContext - Chain context for signing (chainType + chainId + tokenNetworkAddress)
|
|
878
1057
|
* @param initialNonce - Starting nonce (default: 0)
|
|
879
1058
|
* @param initialAmount - Starting cumulative amount (default: 0n)
|
|
880
1059
|
*/
|
|
881
1060
|
trackChannel(channelId: string, chainContext?: {
|
|
1061
|
+
chainType?: string;
|
|
882
1062
|
chainId: number;
|
|
883
1063
|
tokenNetworkAddress: string;
|
|
884
1064
|
tokenAddress?: string;
|
|
@@ -886,6 +1066,7 @@ declare class ChannelManager {
|
|
|
886
1066
|
/**
|
|
887
1067
|
* Signs a balance proof for the given channel.
|
|
888
1068
|
* Auto-increments nonce and adds to cumulative amount.
|
|
1069
|
+
* Routes to the correct ChainSigner based on the channel's chain type.
|
|
889
1070
|
*
|
|
890
1071
|
* @param channelId - Payment channel identifier
|
|
891
1072
|
* @param additionalAmount - Amount to add to cumulative transferred amount
|
|
@@ -893,6 +1074,7 @@ declare class ChannelManager {
|
|
|
893
1074
|
* @throws Error if channel is not being tracked
|
|
894
1075
|
*/
|
|
895
1076
|
signBalanceProof(channelId: string, additionalAmount: bigint): Promise<SignedBalanceProof>;
|
|
1077
|
+
private buildMetadata;
|
|
896
1078
|
/**
|
|
897
1079
|
* Gets the current nonce for a tracked channel.
|
|
898
1080
|
*/
|
|
@@ -1005,4 +1187,258 @@ declare function applyDefaults(config: ToonClientConfig): ResolvedConfig;
|
|
|
1005
1187
|
*/
|
|
1006
1188
|
declare function buildSettlementInfo(config: ToonClientConfig): ClientSettlementInfo | undefined;
|
|
1007
1189
|
|
|
1008
|
-
|
|
1190
|
+
/**
|
|
1191
|
+
* Full multi-chain identity derived from a single BIP-39 mnemonic.
|
|
1192
|
+
*/
|
|
1193
|
+
interface ToonIdentity {
|
|
1194
|
+
nostr: {
|
|
1195
|
+
secretKey: Uint8Array;
|
|
1196
|
+
pubkey: string;
|
|
1197
|
+
};
|
|
1198
|
+
evm: {
|
|
1199
|
+
privateKey: Uint8Array;
|
|
1200
|
+
address: string;
|
|
1201
|
+
};
|
|
1202
|
+
solana: {
|
|
1203
|
+
secretKey: Uint8Array;
|
|
1204
|
+
publicKey: string;
|
|
1205
|
+
};
|
|
1206
|
+
mina: {
|
|
1207
|
+
privateKey: string;
|
|
1208
|
+
publicKey: string;
|
|
1209
|
+
};
|
|
1210
|
+
}
|
|
1211
|
+
/**
|
|
1212
|
+
* Signer accessors provided by KeyManager after create/recover.
|
|
1213
|
+
*/
|
|
1214
|
+
interface ToonSigners {
|
|
1215
|
+
evm: EvmSigner;
|
|
1216
|
+
solana: SolanaSigner;
|
|
1217
|
+
mina: MinaSigner;
|
|
1218
|
+
}
|
|
1219
|
+
/**
|
|
1220
|
+
* Metadata about a registered WebAuthn credential.
|
|
1221
|
+
*/
|
|
1222
|
+
interface PasskeyInfo {
|
|
1223
|
+
credentialIdHash: string;
|
|
1224
|
+
createdAt: number;
|
|
1225
|
+
}
|
|
1226
|
+
/**
|
|
1227
|
+
* Configuration for the KeyManager.
|
|
1228
|
+
*/
|
|
1229
|
+
interface KeyManagerConfig {
|
|
1230
|
+
relayUrls: string[];
|
|
1231
|
+
rpId?: string;
|
|
1232
|
+
rpName?: string;
|
|
1233
|
+
storageKey?: string;
|
|
1234
|
+
}
|
|
1235
|
+
/**
|
|
1236
|
+
* Encrypted backup payload stored in kind:30078 event content.
|
|
1237
|
+
*/
|
|
1238
|
+
interface BackupPayload {
|
|
1239
|
+
encrypted_mnemonic: string;
|
|
1240
|
+
wrapped_keys: WrappedKeyEntry[];
|
|
1241
|
+
recovery_code_wrapped_dek?: string;
|
|
1242
|
+
iv: string;
|
|
1243
|
+
}
|
|
1244
|
+
/**
|
|
1245
|
+
* A single wrapped DEK entry, keyed to a specific WebAuthn credential.
|
|
1246
|
+
*/
|
|
1247
|
+
interface WrappedKeyEntry {
|
|
1248
|
+
id: string;
|
|
1249
|
+
wrapped_dek: string;
|
|
1250
|
+
salt: string;
|
|
1251
|
+
created_at: number;
|
|
1252
|
+
}
|
|
1253
|
+
/**
|
|
1254
|
+
* Vault data persisted to IndexedDB.
|
|
1255
|
+
*/
|
|
1256
|
+
interface VaultData {
|
|
1257
|
+
encryptedMnemonic: string;
|
|
1258
|
+
iv: string;
|
|
1259
|
+
wrappedKeys: WrappedKeyEntry[];
|
|
1260
|
+
recoveryCodeWrappedDek?: string;
|
|
1261
|
+
recoveryCodeSalt?: string;
|
|
1262
|
+
}
|
|
1263
|
+
|
|
1264
|
+
/**
|
|
1265
|
+
* KeyManager orchestrates the full key lifecycle:
|
|
1266
|
+
* generate, derive, store, backup, recover — gated by WebAuthn Passkeys.
|
|
1267
|
+
*
|
|
1268
|
+
* Usage:
|
|
1269
|
+
* const km = new KeyManager({ relayUrls: ['wss://relay.example'] });
|
|
1270
|
+
* const identity = await km.create();
|
|
1271
|
+
* // or: const identity = await km.recover();
|
|
1272
|
+
*
|
|
1273
|
+
* const client = new ToonClient({
|
|
1274
|
+
* secretKey: identity.nostr.secretKey,
|
|
1275
|
+
* // ...
|
|
1276
|
+
* });
|
|
1277
|
+
*
|
|
1278
|
+
* Security note: JavaScript strings (like mnemonics) are immutable and cannot be
|
|
1279
|
+
* zeroed from memory. Uint8Array key material is zeroed on lock(), but mnemonic
|
|
1280
|
+
* strings persist until garbage collected. This is a known JS platform limitation.
|
|
1281
|
+
*/
|
|
1282
|
+
declare class KeyManager {
|
|
1283
|
+
private readonly config;
|
|
1284
|
+
private identity;
|
|
1285
|
+
private vault;
|
|
1286
|
+
private activeCredentialIdHash;
|
|
1287
|
+
constructor(config: KeyManagerConfig);
|
|
1288
|
+
/**
|
|
1289
|
+
* Create a new account: generate mnemonic, create Passkey, encrypt, backup.
|
|
1290
|
+
*/
|
|
1291
|
+
create(): Promise<ToonIdentity>;
|
|
1292
|
+
/**
|
|
1293
|
+
* Recover an account using a synced Passkey.
|
|
1294
|
+
* The Nostr pubkey is extracted from the Passkey's userHandle.
|
|
1295
|
+
*
|
|
1296
|
+
* Flow: single assertion → userHandle → fetch backup → derive KEK → unlock.
|
|
1297
|
+
* If the local vault is available (has the PRF salt), we use a single assertion
|
|
1298
|
+
* with the correct salt. Otherwise, we need the backup from relays first, which
|
|
1299
|
+
* requires a discovery assertion to get the pubkey.
|
|
1300
|
+
*/
|
|
1301
|
+
recover(): Promise<ToonIdentity>;
|
|
1302
|
+
/**
|
|
1303
|
+
* Import an existing BIP-39 mnemonic. Creates a Passkey and backup.
|
|
1304
|
+
*/
|
|
1305
|
+
importMnemonic(mnemonic: string): Promise<ToonIdentity>;
|
|
1306
|
+
/**
|
|
1307
|
+
* Import from an nsec (Nostr-only key).
|
|
1308
|
+
* Nostr + EVM are derived; Solana + Mina get fresh keys (not deterministically linked).
|
|
1309
|
+
*/
|
|
1310
|
+
importNsec(nsec: string): Promise<ToonIdentity>;
|
|
1311
|
+
/**
|
|
1312
|
+
* Register an additional Passkey for this identity.
|
|
1313
|
+
*/
|
|
1314
|
+
addPasskey(): Promise<void>;
|
|
1315
|
+
/**
|
|
1316
|
+
* List registered Passkey credentials.
|
|
1317
|
+
*/
|
|
1318
|
+
listPasskeys(): PasskeyInfo[];
|
|
1319
|
+
/**
|
|
1320
|
+
* Remove a Passkey from the vault. Cannot remove the last one.
|
|
1321
|
+
*/
|
|
1322
|
+
removePasskey(credentialIdHash: string): Promise<void>;
|
|
1323
|
+
/**
|
|
1324
|
+
* Generate a printable recovery code and add it to the vault.
|
|
1325
|
+
* The PBKDF2 salt is persisted alongside the wrapped DEK so the code
|
|
1326
|
+
* can be verified later without the original salt.
|
|
1327
|
+
*
|
|
1328
|
+
* @returns The recovery code — user must store it securely.
|
|
1329
|
+
*/
|
|
1330
|
+
generateRecoveryCode(): Promise<string>;
|
|
1331
|
+
/**
|
|
1332
|
+
* Recover identity using a recovery code.
|
|
1333
|
+
* The PBKDF2 salt is read from the persisted vault data.
|
|
1334
|
+
*/
|
|
1335
|
+
recoverWithCode(code: string): Promise<ToonIdentity>;
|
|
1336
|
+
/**
|
|
1337
|
+
* Get the current identity, or null if not unlocked.
|
|
1338
|
+
*/
|
|
1339
|
+
getIdentity(): ToonIdentity | null;
|
|
1340
|
+
/**
|
|
1341
|
+
* Get the Nostr secret key. Throws if not unlocked.
|
|
1342
|
+
*/
|
|
1343
|
+
getNostrSecretKey(): Uint8Array;
|
|
1344
|
+
/**
|
|
1345
|
+
* Get an EvmSigner instance. Throws if not unlocked.
|
|
1346
|
+
*/
|
|
1347
|
+
getEvmSigner(): EvmSigner;
|
|
1348
|
+
/**
|
|
1349
|
+
* Get a SolanaSigner instance. Throws if not unlocked or Solana not derived.
|
|
1350
|
+
*/
|
|
1351
|
+
getSolanaSigner(): SolanaSigner;
|
|
1352
|
+
/**
|
|
1353
|
+
* Get a MinaSigner instance. Throws if not unlocked or Mina not derived.
|
|
1354
|
+
*/
|
|
1355
|
+
getMinaSigner(): MinaSigner;
|
|
1356
|
+
/**
|
|
1357
|
+
* Publish the current vault to configured relays as a kind:30078 event.
|
|
1358
|
+
*/
|
|
1359
|
+
backupToRelay(): Promise<void>;
|
|
1360
|
+
/**
|
|
1361
|
+
* Clear keys from memory. The vault remains in IndexedDB.
|
|
1362
|
+
* Note: JavaScript strings (mnemonics) cannot be zeroed — only Uint8Array keys are cleared.
|
|
1363
|
+
*/
|
|
1364
|
+
lock(): void;
|
|
1365
|
+
/**
|
|
1366
|
+
* Re-assert Passkey to decrypt local vault and restore identity.
|
|
1367
|
+
* Uses the local vault's stored PRF salt for a single biometric prompt.
|
|
1368
|
+
*/
|
|
1369
|
+
unlock(): Promise<ToonIdentity>;
|
|
1370
|
+
/**
|
|
1371
|
+
* Unlock a vault with a single Passkey assertion using stored PRF salts.
|
|
1372
|
+
* If the vault has only one credential, uses allowCredentials to constrain.
|
|
1373
|
+
*/
|
|
1374
|
+
private unlockWithVault;
|
|
1375
|
+
private saveToLocalStorage;
|
|
1376
|
+
private loadFromLocalStorage;
|
|
1377
|
+
}
|
|
1378
|
+
|
|
1379
|
+
/**
|
|
1380
|
+
* Generate a new 12-word BIP-39 mnemonic.
|
|
1381
|
+
*/
|
|
1382
|
+
declare function generateMnemonic(): string;
|
|
1383
|
+
/**
|
|
1384
|
+
* Validate a BIP-39 mnemonic phrase.
|
|
1385
|
+
*/
|
|
1386
|
+
declare function validateMnemonic(mnemonic: string): boolean;
|
|
1387
|
+
/**
|
|
1388
|
+
* Derive a full multi-chain ToonIdentity from a BIP-39 mnemonic.
|
|
1389
|
+
*
|
|
1390
|
+
* Chains derived:
|
|
1391
|
+
* - Nostr (secp256k1): m/44'/1237'/0'/0/0
|
|
1392
|
+
* - EVM (secp256k1): same key as Nostr
|
|
1393
|
+
* - Solana (Ed25519): m/44'/501'/0'/0' (SLIP-0010)
|
|
1394
|
+
* - Mina (Pallas): m/44'/12586'/0'/0/0
|
|
1395
|
+
*/
|
|
1396
|
+
declare function deriveFullIdentity(mnemonic: string): Promise<ToonIdentity>;
|
|
1397
|
+
/**
|
|
1398
|
+
* Derive a partial identity from an nsec (Nostr-only private key).
|
|
1399
|
+
* Nostr + EVM share the same secp256k1 key.
|
|
1400
|
+
* Solana and Mina get empty placeholders (not deterministically linked).
|
|
1401
|
+
*/
|
|
1402
|
+
declare function deriveFromNsec(secretKey: Uint8Array): ToonIdentity;
|
|
1403
|
+
/**
|
|
1404
|
+
* Generate a random identity (no mnemonic — for testing or ephemeral use).
|
|
1405
|
+
*/
|
|
1406
|
+
declare function generateRandomIdentity(): ToonIdentity;
|
|
1407
|
+
|
|
1408
|
+
/**
|
|
1409
|
+
* Build a kind:30078 Nostr event for identity backup.
|
|
1410
|
+
* The event must be signed by the caller before publishing.
|
|
1411
|
+
*
|
|
1412
|
+
* @param vault - The encrypted vault data
|
|
1413
|
+
* @param secretKey - Nostr secret key for signing
|
|
1414
|
+
* @param chains - Comma-separated list of supported chains
|
|
1415
|
+
* @returns Unsigned Nostr event template
|
|
1416
|
+
*/
|
|
1417
|
+
declare function buildBackupEvent(vault: VaultData, secretKey: Uint8Array, chains?: string): {
|
|
1418
|
+
kind: number;
|
|
1419
|
+
pubkey: string;
|
|
1420
|
+
created_at: number;
|
|
1421
|
+
tags: string[][];
|
|
1422
|
+
content: string;
|
|
1423
|
+
};
|
|
1424
|
+
/**
|
|
1425
|
+
* Build a relay filter to fetch the identity backup for a given pubkey.
|
|
1426
|
+
*/
|
|
1427
|
+
declare function buildBackupFilter(pubkey: string): {
|
|
1428
|
+
kinds: number[];
|
|
1429
|
+
authors: string[];
|
|
1430
|
+
'#d': string[];
|
|
1431
|
+
};
|
|
1432
|
+
/**
|
|
1433
|
+
* Parse a backup event's content into VaultData.
|
|
1434
|
+
* Validates the structure before returning.
|
|
1435
|
+
*/
|
|
1436
|
+
declare function parseBackupPayload(content: string): VaultData;
|
|
1437
|
+
|
|
1438
|
+
/**
|
|
1439
|
+
* Check whether the current browser supports WebAuthn with PRF extension.
|
|
1440
|
+
* Returns false in Node.js or browsers without PublicKeyCredential.
|
|
1441
|
+
*/
|
|
1442
|
+
declare function isPrfSupported(): boolean;
|
|
1443
|
+
|
|
1444
|
+
export { type BackupPayload, type BalanceProofParams, BtpRuntimeClient, type BtpRuntimeClientConfig, ChannelManager, ConnectorError, type EVMClaimMessage, EvmSigner, HttpConnectorAdmin, type HttpConnectorAdminConfig, HttpRuntimeClient, type HttpRuntimeClientConfig, KeyManager, type KeyManagerConfig, NetworkError, OnChainChannelClient, type OnChainChannelClientConfig, type PasskeyInfo, type PublishEventResult, type RetryOptions, type SignedBalanceProof, ToonClient, type ToonClientConfig, ToonClientError, type ToonIdentity, type ToonSigners, type ToonStartResult, ValidationError, type VaultData, applyDefaults, buildBackupEvent, buildBackupFilter, buildSettlementInfo, deriveFromNsec, deriveFullIdentity, generateMnemonic, generateRandomIdentity, isPrfSupported, parseBackupPayload, validateConfig, validateMnemonic, withRetry };
|