@unicitylabs/sphere-sdk 0.3.9 → 0.4.0
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/dist/connect/index.cjs +1 -1
- package/dist/connect/index.cjs.map +1 -1
- package/dist/connect/index.js +1 -1
- package/dist/connect/index.js.map +1 -1
- package/dist/core/index.cjs +2657 -49
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +221 -3
- package/dist/core/index.d.ts +221 -3
- package/dist/core/index.js +2653 -45
- package/dist/core/index.js.map +1 -1
- package/dist/impl/browser/index.cjs +450 -47
- package/dist/impl/browser/index.cjs.map +1 -1
- package/dist/impl/browser/index.js +451 -47
- package/dist/impl/browser/index.js.map +1 -1
- package/dist/impl/nodejs/index.cjs +152 -8
- package/dist/impl/nodejs/index.cjs.map +1 -1
- package/dist/impl/nodejs/index.d.cts +47 -0
- package/dist/impl/nodejs/index.d.ts +47 -0
- package/dist/impl/nodejs/index.js +153 -8
- package/dist/impl/nodejs/index.js.map +1 -1
- package/dist/index.cjs +2674 -49
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +319 -5
- package/dist/index.d.ts +319 -5
- package/dist/index.js +2663 -45
- package/dist/index.js.map +1 -1
- package/dist/l1/index.cjs +5 -1
- package/dist/l1/index.cjs.map +1 -1
- package/dist/l1/index.d.cts +2 -1
- package/dist/l1/index.d.ts +2 -1
- package/dist/l1/index.js +5 -1
- package/dist/l1/index.js.map +1 -1
- package/package.json +1 -1
package/dist/core/index.d.cts
CHANGED
|
@@ -655,6 +655,11 @@ interface BroadcastMessage {
|
|
|
655
655
|
readonly timestamp: number;
|
|
656
656
|
readonly tags?: string[];
|
|
657
657
|
}
|
|
658
|
+
interface ComposingIndicator {
|
|
659
|
+
readonly senderPubkey: string;
|
|
660
|
+
readonly senderNametag?: string;
|
|
661
|
+
readonly expiresIn: number;
|
|
662
|
+
}
|
|
658
663
|
/**
|
|
659
664
|
* Minimal data stored in persistent storage for a tracked address.
|
|
660
665
|
* Only contains user state — derived fields are computed on load.
|
|
@@ -685,7 +690,7 @@ interface TrackedAddress extends TrackedAddressEntry {
|
|
|
685
690
|
/** Primary nametag (from nametag cache, without @ prefix) */
|
|
686
691
|
readonly nametag?: string;
|
|
687
692
|
}
|
|
688
|
-
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:read' | 'message:typing' | 'message:broadcast' | 'sync:started' | 'sync:completed' | 'sync:provider' | 'sync:error' | 'connection:changed' | 'nametag:registered' | 'nametag:recovered' | 'identity:changed' | 'address:activated' | 'address:hidden' | 'address:unhidden' | 'sync:remote-update' | 'groupchat:message' | 'groupchat:joined' | 'groupchat:left' | 'groupchat:kicked' | 'groupchat:group_deleted' | 'groupchat:updated' | 'groupchat:connection';
|
|
693
|
+
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:read' | 'message:typing' | 'composing:started' | 'message:broadcast' | 'sync:started' | 'sync:completed' | 'sync:provider' | 'sync:error' | 'connection:changed' | 'nametag:registered' | 'nametag:recovered' | 'identity:changed' | 'address:activated' | 'address:hidden' | 'address:unhidden' | 'sync:remote-update' | 'groupchat:message' | 'groupchat:joined' | 'groupchat:left' | 'groupchat:kicked' | 'groupchat:group_deleted' | 'groupchat:updated' | 'groupchat:connection';
|
|
689
694
|
interface SphereEventMap {
|
|
690
695
|
'transfer:incoming': IncomingTransfer;
|
|
691
696
|
'transfer:confirmed': TransferResult;
|
|
@@ -705,6 +710,7 @@ interface SphereEventMap {
|
|
|
705
710
|
senderNametag?: string;
|
|
706
711
|
timestamp: number;
|
|
707
712
|
};
|
|
713
|
+
'composing:started': ComposingIndicator;
|
|
708
714
|
'message:broadcast': BroadcastMessage;
|
|
709
715
|
'sync:started': {
|
|
710
716
|
source: string;
|
|
@@ -1053,6 +1059,17 @@ interface TransportProvider extends BaseProvider {
|
|
|
1053
1059
|
* @returns Unsubscribe function
|
|
1054
1060
|
*/
|
|
1055
1061
|
onTypingIndicator?(handler: TypingIndicatorHandler): () => void;
|
|
1062
|
+
/**
|
|
1063
|
+
* Send composing indicator to a recipient using NIP-44 encrypted gift wrap
|
|
1064
|
+
* @param recipientTransportPubkey - Transport pubkey of the conversation partner
|
|
1065
|
+
* @param content - JSON payload with senderNametag and expiresIn
|
|
1066
|
+
*/
|
|
1067
|
+
sendComposingIndicator?(recipientTransportPubkey: string, content: string): Promise<void>;
|
|
1068
|
+
/**
|
|
1069
|
+
* Subscribe to incoming composing indicators
|
|
1070
|
+
* @returns Unsubscribe function
|
|
1071
|
+
*/
|
|
1072
|
+
onComposing?(handler: ComposingHandler): () => void;
|
|
1056
1073
|
/**
|
|
1057
1074
|
* Get list of configured relay URLs
|
|
1058
1075
|
*/
|
|
@@ -1277,6 +1294,7 @@ interface IncomingTypingIndicator {
|
|
|
1277
1294
|
timestamp: number;
|
|
1278
1295
|
}
|
|
1279
1296
|
type TypingIndicatorHandler = (indicator: IncomingTypingIndicator) => void;
|
|
1297
|
+
type ComposingHandler = (indicator: ComposingIndicator) => void;
|
|
1280
1298
|
|
|
1281
1299
|
/**
|
|
1282
1300
|
* L1 Payments Sub-Module
|
|
@@ -2492,6 +2510,11 @@ declare class PaymentsModule {
|
|
|
2492
2510
|
* Create SigningService from identity private key
|
|
2493
2511
|
*/
|
|
2494
2512
|
private createSigningService;
|
|
2513
|
+
/**
|
|
2514
|
+
* Get the wallet's signing public key (used for token ownership predicates).
|
|
2515
|
+
* This is the key that token state predicates are checked against.
|
|
2516
|
+
*/
|
|
2517
|
+
getSigningPublicKey(): Promise<Uint8Array>;
|
|
2495
2518
|
/**
|
|
2496
2519
|
* Create DirectAddress from a public key using UnmaskedPredicateReference
|
|
2497
2520
|
*/
|
|
@@ -2556,11 +2579,24 @@ declare class PaymentsModule {
|
|
|
2556
2579
|
interface CommunicationsModuleConfig {
|
|
2557
2580
|
/** Auto-save messages */
|
|
2558
2581
|
autoSave?: boolean;
|
|
2559
|
-
/** Max messages in memory */
|
|
2582
|
+
/** Max messages in memory (global cap) */
|
|
2560
2583
|
maxMessages?: number;
|
|
2584
|
+
/** Max messages per conversation (default: 200) */
|
|
2585
|
+
maxPerConversation?: number;
|
|
2561
2586
|
/** Enable read receipts */
|
|
2562
2587
|
readReceipts?: boolean;
|
|
2563
2588
|
}
|
|
2589
|
+
interface ConversationPage {
|
|
2590
|
+
messages: DirectMessage[];
|
|
2591
|
+
hasMore: boolean;
|
|
2592
|
+
oldestTimestamp: number | null;
|
|
2593
|
+
}
|
|
2594
|
+
interface GetConversationPageOptions {
|
|
2595
|
+
/** Max messages to return (default: 20) */
|
|
2596
|
+
limit?: number;
|
|
2597
|
+
/** Return messages older than this timestamp */
|
|
2598
|
+
before?: number;
|
|
2599
|
+
}
|
|
2564
2600
|
interface CommunicationsModuleDependencies {
|
|
2565
2601
|
identity: FullIdentity;
|
|
2566
2602
|
storage: StorageProvider;
|
|
@@ -2573,8 +2609,10 @@ declare class CommunicationsModule {
|
|
|
2573
2609
|
private messages;
|
|
2574
2610
|
private broadcasts;
|
|
2575
2611
|
private unsubscribeMessages;
|
|
2612
|
+
private unsubscribeComposing;
|
|
2576
2613
|
private broadcastSubscriptions;
|
|
2577
2614
|
private dmHandlers;
|
|
2615
|
+
private composingHandlers;
|
|
2578
2616
|
private broadcastHandlers;
|
|
2579
2617
|
constructor(config?: CommunicationsModuleConfig);
|
|
2580
2618
|
/**
|
|
@@ -2582,7 +2620,10 @@ declare class CommunicationsModule {
|
|
|
2582
2620
|
*/
|
|
2583
2621
|
initialize(deps: CommunicationsModuleDependencies): void;
|
|
2584
2622
|
/**
|
|
2585
|
-
* Load messages from storage
|
|
2623
|
+
* Load messages from storage.
|
|
2624
|
+
* Uses per-address key (STORAGE_KEYS_ADDRESS.MESSAGES) which is automatically
|
|
2625
|
+
* scoped by LocalStorageProvider to sphere_DIRECT_xxx_yyy_messages.
|
|
2626
|
+
* Falls back to legacy global 'direct_messages' key for migration.
|
|
2586
2627
|
*/
|
|
2587
2628
|
load(): Promise<void>;
|
|
2588
2629
|
/**
|
|
@@ -2609,10 +2650,28 @@ declare class CommunicationsModule {
|
|
|
2609
2650
|
* Get unread count
|
|
2610
2651
|
*/
|
|
2611
2652
|
getUnreadCount(peerPubkey?: string): number;
|
|
2653
|
+
/**
|
|
2654
|
+
* Get a page of messages from a conversation (for lazy loading).
|
|
2655
|
+
* Returns messages in chronological order with a cursor for loading older messages.
|
|
2656
|
+
*/
|
|
2657
|
+
getConversationPage(peerPubkey: string, options?: GetConversationPageOptions): ConversationPage;
|
|
2658
|
+
/**
|
|
2659
|
+
* Delete all messages in a conversation with a peer
|
|
2660
|
+
*/
|
|
2661
|
+
deleteConversation(peerPubkey: string): Promise<void>;
|
|
2612
2662
|
/**
|
|
2613
2663
|
* Send typing indicator to a peer
|
|
2614
2664
|
*/
|
|
2615
2665
|
sendTypingIndicator(peerPubkey: string): Promise<void>;
|
|
2666
|
+
/**
|
|
2667
|
+
* Send a composing indicator to a peer.
|
|
2668
|
+
* Fire-and-forget — does not save to message history.
|
|
2669
|
+
*/
|
|
2670
|
+
sendComposingIndicator(recipientPubkeyOrNametag: string): Promise<void>;
|
|
2671
|
+
/**
|
|
2672
|
+
* Subscribe to incoming composing indicators
|
|
2673
|
+
*/
|
|
2674
|
+
onComposingIndicator(handler: (indicator: ComposingIndicator) => void): () => void;
|
|
2616
2675
|
/**
|
|
2617
2676
|
* Subscribe to incoming DMs
|
|
2618
2677
|
*/
|
|
@@ -2634,6 +2693,7 @@ declare class CommunicationsModule {
|
|
|
2634
2693
|
*/
|
|
2635
2694
|
onBroadcast(handler: (message: BroadcastMessage) => void): () => void;
|
|
2636
2695
|
private handleIncomingMessage;
|
|
2696
|
+
private handleComposingIndicator;
|
|
2637
2697
|
private handleIncomingBroadcast;
|
|
2638
2698
|
private save;
|
|
2639
2699
|
private pruneIfNeeded;
|
|
@@ -2761,6 +2821,146 @@ declare class GroupChatModule {
|
|
|
2761
2821
|
private randomId;
|
|
2762
2822
|
}
|
|
2763
2823
|
|
|
2824
|
+
/**
|
|
2825
|
+
* Market Module Types
|
|
2826
|
+
* Intent bulletin board for posting and discovering intents,
|
|
2827
|
+
* plus real-time feed subscription.
|
|
2828
|
+
*/
|
|
2829
|
+
type IntentType = 'buy' | 'sell' | 'service' | 'announcement' | 'other' | (string & {});
|
|
2830
|
+
type IntentStatus = 'active' | 'closed' | 'expired';
|
|
2831
|
+
interface MarketModuleConfig {
|
|
2832
|
+
/** Market API base URL (default: https://market-api.unicity.network) */
|
|
2833
|
+
apiUrl?: string;
|
|
2834
|
+
/** Request timeout in ms (default: 30000) */
|
|
2835
|
+
timeout?: number;
|
|
2836
|
+
}
|
|
2837
|
+
interface MarketModuleDependencies {
|
|
2838
|
+
identity: FullIdentity;
|
|
2839
|
+
emitEvent: <T extends SphereEventType>(type: T, data: SphereEventMap[T]) => void;
|
|
2840
|
+
}
|
|
2841
|
+
interface PostIntentRequest {
|
|
2842
|
+
description: string;
|
|
2843
|
+
intentType: IntentType;
|
|
2844
|
+
category?: string;
|
|
2845
|
+
price?: number;
|
|
2846
|
+
currency?: string;
|
|
2847
|
+
location?: string;
|
|
2848
|
+
contactHandle?: string;
|
|
2849
|
+
expiresInDays?: number;
|
|
2850
|
+
}
|
|
2851
|
+
interface PostIntentResult {
|
|
2852
|
+
intentId: string;
|
|
2853
|
+
message: string;
|
|
2854
|
+
expiresAt: string;
|
|
2855
|
+
}
|
|
2856
|
+
interface MarketIntent {
|
|
2857
|
+
id: string;
|
|
2858
|
+
intentType: IntentType;
|
|
2859
|
+
category?: string;
|
|
2860
|
+
price?: string;
|
|
2861
|
+
currency: string;
|
|
2862
|
+
location?: string;
|
|
2863
|
+
status: IntentStatus;
|
|
2864
|
+
createdAt: string;
|
|
2865
|
+
expiresAt: string;
|
|
2866
|
+
}
|
|
2867
|
+
interface SearchIntentResult {
|
|
2868
|
+
id: string;
|
|
2869
|
+
score: number;
|
|
2870
|
+
agentNametag?: string;
|
|
2871
|
+
agentPublicKey: string;
|
|
2872
|
+
description: string;
|
|
2873
|
+
intentType: IntentType;
|
|
2874
|
+
category?: string;
|
|
2875
|
+
price?: number;
|
|
2876
|
+
currency: string;
|
|
2877
|
+
location?: string;
|
|
2878
|
+
contactMethod: string;
|
|
2879
|
+
contactHandle?: string;
|
|
2880
|
+
createdAt: string;
|
|
2881
|
+
expiresAt: string;
|
|
2882
|
+
}
|
|
2883
|
+
interface SearchFilters {
|
|
2884
|
+
intentType?: IntentType;
|
|
2885
|
+
category?: string;
|
|
2886
|
+
minPrice?: number;
|
|
2887
|
+
maxPrice?: number;
|
|
2888
|
+
location?: string;
|
|
2889
|
+
/** Minimum similarity score (0–1). Results below this threshold are excluded (client-side). */
|
|
2890
|
+
minScore?: number;
|
|
2891
|
+
}
|
|
2892
|
+
interface SearchOptions {
|
|
2893
|
+
filters?: SearchFilters;
|
|
2894
|
+
limit?: number;
|
|
2895
|
+
}
|
|
2896
|
+
interface SearchResult {
|
|
2897
|
+
intents: SearchIntentResult[];
|
|
2898
|
+
count: number;
|
|
2899
|
+
}
|
|
2900
|
+
/** A listing broadcast on the live feed */
|
|
2901
|
+
interface FeedListing {
|
|
2902
|
+
id: string;
|
|
2903
|
+
title: string;
|
|
2904
|
+
descriptionPreview: string;
|
|
2905
|
+
agentName: string;
|
|
2906
|
+
agentId: number;
|
|
2907
|
+
type: IntentType;
|
|
2908
|
+
createdAt: string;
|
|
2909
|
+
}
|
|
2910
|
+
/** WebSocket message: initial batch of recent listings */
|
|
2911
|
+
interface FeedInitialMessage {
|
|
2912
|
+
type: 'initial';
|
|
2913
|
+
listings: FeedListing[];
|
|
2914
|
+
}
|
|
2915
|
+
/** WebSocket message: single new listing */
|
|
2916
|
+
interface FeedNewMessage {
|
|
2917
|
+
type: 'new';
|
|
2918
|
+
listing: FeedListing;
|
|
2919
|
+
}
|
|
2920
|
+
type FeedMessage = FeedInitialMessage | FeedNewMessage;
|
|
2921
|
+
/** Callback for live feed events */
|
|
2922
|
+
type FeedListener = (message: FeedMessage) => void;
|
|
2923
|
+
|
|
2924
|
+
declare class MarketModule {
|
|
2925
|
+
private readonly apiUrl;
|
|
2926
|
+
private readonly timeout;
|
|
2927
|
+
private identity;
|
|
2928
|
+
private registered;
|
|
2929
|
+
constructor(config?: MarketModuleConfig);
|
|
2930
|
+
/** Called by Sphere after construction */
|
|
2931
|
+
initialize(deps: MarketModuleDependencies): void;
|
|
2932
|
+
/** No-op — stateless module */
|
|
2933
|
+
load(): Promise<void>;
|
|
2934
|
+
/** No-op — stateless module */
|
|
2935
|
+
destroy(): void;
|
|
2936
|
+
/** Post a new intent (agent is auto-registered on first post) */
|
|
2937
|
+
postIntent(intent: PostIntentRequest): Promise<PostIntentResult>;
|
|
2938
|
+
/** Semantic search for intents (public — no auth required) */
|
|
2939
|
+
search(query: string, opts?: SearchOptions): Promise<SearchResult>;
|
|
2940
|
+
/** List own intents (authenticated) */
|
|
2941
|
+
getMyIntents(): Promise<MarketIntent[]>;
|
|
2942
|
+
/** Close (delete) an intent */
|
|
2943
|
+
closeIntent(intentId: string): Promise<void>;
|
|
2944
|
+
/** Fetch the most recent listings via REST (public — no auth required) */
|
|
2945
|
+
getRecentListings(): Promise<FeedListing[]>;
|
|
2946
|
+
/**
|
|
2947
|
+
* Subscribe to the live listing feed via WebSocket.
|
|
2948
|
+
* Returns an unsubscribe function that closes the connection.
|
|
2949
|
+
*
|
|
2950
|
+
* Requires a WebSocket implementation — works natively in browsers
|
|
2951
|
+
* and in Node.js 21+ (or with the `ws` package).
|
|
2952
|
+
*/
|
|
2953
|
+
subscribeFeed(listener: FeedListener): () => void;
|
|
2954
|
+
private ensureIdentity;
|
|
2955
|
+
/** Register the agent's public key with the server (idempotent) */
|
|
2956
|
+
private ensureRegistered;
|
|
2957
|
+
private parseResponse;
|
|
2958
|
+
private apiPost;
|
|
2959
|
+
private apiGet;
|
|
2960
|
+
private apiDelete;
|
|
2961
|
+
private apiPublicPost;
|
|
2962
|
+
}
|
|
2963
|
+
|
|
2764
2964
|
/** Network configurations */
|
|
2765
2965
|
declare const NETWORKS: {
|
|
2766
2966
|
readonly mainnet: {
|
|
@@ -2904,6 +3104,8 @@ interface SphereCreateOptions {
|
|
|
2904
3104
|
network?: NetworkType;
|
|
2905
3105
|
/** Group chat configuration (NIP-29). Omit to disable groupchat. */
|
|
2906
3106
|
groupChat?: GroupChatModuleConfig | boolean;
|
|
3107
|
+
/** Market module configuration. true = enable with defaults, object = custom config. */
|
|
3108
|
+
market?: MarketModuleConfig | boolean;
|
|
2907
3109
|
/** Optional password to encrypt the wallet. If omitted, mnemonic is stored as plaintext. */
|
|
2908
3110
|
password?: string;
|
|
2909
3111
|
}
|
|
@@ -2929,6 +3131,8 @@ interface SphereLoadOptions {
|
|
|
2929
3131
|
network?: NetworkType;
|
|
2930
3132
|
/** Group chat configuration (NIP-29). Omit to disable groupchat. */
|
|
2931
3133
|
groupChat?: GroupChatModuleConfig | boolean;
|
|
3134
|
+
/** Market module configuration. true = enable with defaults, object = custom config. */
|
|
3135
|
+
market?: MarketModuleConfig | boolean;
|
|
2932
3136
|
/** Optional password to decrypt the wallet. Must match the password used during creation. */
|
|
2933
3137
|
password?: string;
|
|
2934
3138
|
}
|
|
@@ -2962,6 +3166,8 @@ interface SphereImportOptions {
|
|
|
2962
3166
|
price?: PriceProvider;
|
|
2963
3167
|
/** Group chat configuration (NIP-29). Omit to disable groupchat. */
|
|
2964
3168
|
groupChat?: GroupChatModuleConfig | boolean;
|
|
3169
|
+
/** Market module configuration. true = enable with defaults, object = custom config. */
|
|
3170
|
+
market?: MarketModuleConfig | boolean;
|
|
2965
3171
|
/** Optional password to encrypt the wallet. If omitted, mnemonic/key is stored as plaintext. */
|
|
2966
3172
|
password?: string;
|
|
2967
3173
|
}
|
|
@@ -3009,6 +3215,8 @@ interface SphereInitOptions {
|
|
|
3009
3215
|
* - Omit/undefined: No groupchat module
|
|
3010
3216
|
*/
|
|
3011
3217
|
groupChat?: GroupChatModuleConfig | boolean;
|
|
3218
|
+
/** Market module configuration. true = enable with defaults, object = custom config. */
|
|
3219
|
+
market?: MarketModuleConfig | boolean;
|
|
3012
3220
|
/** Optional password to encrypt/decrypt the wallet. If omitted, mnemonic is stored as plaintext. */
|
|
3013
3221
|
password?: string;
|
|
3014
3222
|
}
|
|
@@ -3048,6 +3256,7 @@ declare class Sphere {
|
|
|
3048
3256
|
private _payments;
|
|
3049
3257
|
private _communications;
|
|
3050
3258
|
private _groupChat;
|
|
3259
|
+
private _market;
|
|
3051
3260
|
private eventHandlers;
|
|
3052
3261
|
private _disabledProviders;
|
|
3053
3262
|
private _providerEventCleanups;
|
|
@@ -3095,6 +3304,13 @@ declare class Sphere {
|
|
|
3095
3304
|
* (different input shape: { enabled?, relays? }). Both fill relay URLs from network defaults.
|
|
3096
3305
|
*/
|
|
3097
3306
|
private static resolveGroupChatConfig;
|
|
3307
|
+
/**
|
|
3308
|
+
* Resolve market module config from Sphere.init() options.
|
|
3309
|
+
* - `true` → enable with default API URL
|
|
3310
|
+
* - `MarketModuleConfig` → pass through
|
|
3311
|
+
* - `undefined` → no market module
|
|
3312
|
+
*/
|
|
3313
|
+
private static resolveMarketConfig;
|
|
3098
3314
|
/**
|
|
3099
3315
|
* Configure TokenRegistry in the main bundle context.
|
|
3100
3316
|
*
|
|
@@ -3163,6 +3379,8 @@ declare class Sphere {
|
|
|
3163
3379
|
get communications(): CommunicationsModule;
|
|
3164
3380
|
/** Group chat module (NIP-29). Null if not configured. */
|
|
3165
3381
|
get groupChat(): GroupChatModule | null;
|
|
3382
|
+
/** Market module (intent bulletin board). Null if not configured. */
|
|
3383
|
+
get market(): MarketModule | null;
|
|
3166
3384
|
/** Current identity (public info only) */
|
|
3167
3385
|
get identity(): Identity | null;
|
|
3168
3386
|
/** Is ready */
|