@partylayer/provider 0.1.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/dist/index.js ADDED
@@ -0,0 +1,938 @@
1
+ 'use strict';
2
+
3
+ var core = require('@partylayer/core');
4
+
5
+ // src/provider.ts
6
+
7
+ // src/event-bus.ts
8
+ var CIP0103EventBus = class {
9
+ listeners = /* @__PURE__ */ new Map();
10
+ owner = null;
11
+ /** Set the owning Provider instance (for chaining returns) */
12
+ setOwner(owner) {
13
+ this.owner = owner;
14
+ }
15
+ on(event, listener) {
16
+ let set = this.listeners.get(event);
17
+ if (!set) {
18
+ set = /* @__PURE__ */ new Set();
19
+ this.listeners.set(event, set);
20
+ }
21
+ set.add(listener);
22
+ return this.owner;
23
+ }
24
+ emit(event, ...args) {
25
+ const set = this.listeners.get(event);
26
+ if (!set || set.size === 0) return false;
27
+ for (const fn of set) {
28
+ try {
29
+ fn(...args);
30
+ } catch {
31
+ }
32
+ }
33
+ return true;
34
+ }
35
+ removeListener(event, listenerToRemove) {
36
+ const set = this.listeners.get(event);
37
+ if (set) {
38
+ set.delete(listenerToRemove);
39
+ if (set.size === 0) this.listeners.delete(event);
40
+ }
41
+ return this.owner;
42
+ }
43
+ /** Remove all listeners, optionally scoped to a single event */
44
+ removeAllListeners(event) {
45
+ if (event) {
46
+ this.listeners.delete(event);
47
+ } else {
48
+ this.listeners.clear();
49
+ }
50
+ }
51
+ /** Number of listeners for a given event */
52
+ listenerCount(event) {
53
+ return this.listeners.get(event)?.size ?? 0;
54
+ }
55
+ };
56
+
57
+ // src/errors.ts
58
+ var ProviderRpcError = class _ProviderRpcError extends Error {
59
+ code;
60
+ data;
61
+ constructor(message, code, data) {
62
+ super(message);
63
+ this.name = "ProviderRpcError";
64
+ this.code = code;
65
+ this.data = data;
66
+ if (Error.captureStackTrace) {
67
+ Error.captureStackTrace(this, _ProviderRpcError);
68
+ }
69
+ }
70
+ toJSON() {
71
+ return {
72
+ name: this.name,
73
+ message: this.message,
74
+ code: this.code,
75
+ data: this.data
76
+ };
77
+ }
78
+ };
79
+ var RPC_ERRORS = {
80
+ /** User rejected the request */
81
+ USER_REJECTED: 4001,
82
+ /** The requested method/account is not authorized */
83
+ UNAUTHORIZED: 4100,
84
+ /** Provider does not support the requested method */
85
+ UNSUPPORTED_METHOD: 4200,
86
+ /** Provider is disconnected from all chains */
87
+ DISCONNECTED: 4900,
88
+ /** Provider is not connected to the requested chain */
89
+ CHAIN_DISCONNECTED: 4901
90
+ };
91
+ var JSON_RPC_ERRORS = {
92
+ /** Invalid JSON (parse error) */
93
+ PARSE_ERROR: -32700,
94
+ /** Invalid request object */
95
+ INVALID_REQUEST: -32600,
96
+ /** Method not found */
97
+ METHOD_NOT_FOUND: -32601,
98
+ /** Invalid method parameters */
99
+ INVALID_PARAMS: -32602,
100
+ /** Internal JSON-RPC error */
101
+ INTERNAL_ERROR: -32603,
102
+ /** Invalid input / missing or invalid parameters */
103
+ INVALID_INPUT: -32e3,
104
+ /** Resource not found */
105
+ RESOURCE_NOT_FOUND: -32001,
106
+ /** Resource unavailable */
107
+ RESOURCE_UNAVAILABLE: -32002,
108
+ /** Transaction rejected */
109
+ TRANSACTION_REJECTED: -32003,
110
+ /** Method not supported */
111
+ METHOD_NOT_SUPPORTED: -32004,
112
+ /** Rate limit exceeded */
113
+ RATE_LIMIT_EXCEEDED: -32005
114
+ };
115
+ function userRejected(message = "User Rejected Request", data) {
116
+ return new ProviderRpcError(message, RPC_ERRORS.USER_REJECTED, data);
117
+ }
118
+ function unauthorized(message = "Unauthorized", data) {
119
+ return new ProviderRpcError(message, RPC_ERRORS.UNAUTHORIZED, data);
120
+ }
121
+ function unsupportedMethod(method) {
122
+ return new ProviderRpcError(
123
+ `Unsupported Method: "${method}"`,
124
+ RPC_ERRORS.UNSUPPORTED_METHOD,
125
+ { method }
126
+ );
127
+ }
128
+ function disconnected(message = "Disconnected") {
129
+ return new ProviderRpcError(message, RPC_ERRORS.DISCONNECTED);
130
+ }
131
+ function chainDisconnected(message = "Chain Disconnected") {
132
+ return new ProviderRpcError(message, RPC_ERRORS.CHAIN_DISCONNECTED);
133
+ }
134
+ function internalError(message, data) {
135
+ return new ProviderRpcError(message, JSON_RPC_ERRORS.INTERNAL_ERROR, data);
136
+ }
137
+ function invalidParams(message, data) {
138
+ return new ProviderRpcError(message, JSON_RPC_ERRORS.INVALID_PARAMS, data);
139
+ }
140
+ function methodNotFound(method) {
141
+ return new ProviderRpcError(
142
+ `Method not found: "${method}"`,
143
+ JSON_RPC_ERRORS.METHOD_NOT_FOUND,
144
+ { method }
145
+ );
146
+ }
147
+ function resourceNotFound(message, data) {
148
+ return new ProviderRpcError(message, JSON_RPC_ERRORS.RESOURCE_NOT_FOUND, data);
149
+ }
150
+ function resourceUnavailable(message, data) {
151
+ return new ProviderRpcError(message, JSON_RPC_ERRORS.RESOURCE_UNAVAILABLE, data);
152
+ }
153
+ function transactionRejected(message = "Transaction rejected", data) {
154
+ return new ProviderRpcError(message, JSON_RPC_ERRORS.TRANSACTION_REJECTED, data);
155
+ }
156
+ var ERROR_CODE_TO_RPC = {
157
+ USER_REJECTED: RPC_ERRORS.USER_REJECTED,
158
+ WALLET_NOT_FOUND: JSON_RPC_ERRORS.RESOURCE_NOT_FOUND,
159
+ WALLET_NOT_INSTALLED: JSON_RPC_ERRORS.RESOURCE_UNAVAILABLE,
160
+ ORIGIN_NOT_ALLOWED: RPC_ERRORS.UNAUTHORIZED,
161
+ SESSION_EXPIRED: RPC_ERRORS.DISCONNECTED,
162
+ CAPABILITY_NOT_SUPPORTED: RPC_ERRORS.UNSUPPORTED_METHOD,
163
+ TRANSPORT_ERROR: JSON_RPC_ERRORS.INTERNAL_ERROR,
164
+ REGISTRY_FETCH_FAILED: JSON_RPC_ERRORS.RESOURCE_UNAVAILABLE,
165
+ REGISTRY_VERIFICATION_FAILED: JSON_RPC_ERRORS.INTERNAL_ERROR,
166
+ REGISTRY_SCHEMA_INVALID: JSON_RPC_ERRORS.INTERNAL_ERROR,
167
+ INTERNAL_ERROR: JSON_RPC_ERRORS.INTERNAL_ERROR,
168
+ TIMEOUT: JSON_RPC_ERRORS.INVALID_INPUT
169
+ };
170
+ var RPC_TO_ERROR_CODE = {
171
+ [RPC_ERRORS.USER_REJECTED]: "USER_REJECTED",
172
+ [RPC_ERRORS.UNAUTHORIZED]: "ORIGIN_NOT_ALLOWED",
173
+ [RPC_ERRORS.UNSUPPORTED_METHOD]: "CAPABILITY_NOT_SUPPORTED",
174
+ [RPC_ERRORS.DISCONNECTED]: "SESSION_EXPIRED",
175
+ [RPC_ERRORS.CHAIN_DISCONNECTED]: "TRANSPORT_ERROR",
176
+ [JSON_RPC_ERRORS.INTERNAL_ERROR]: "INTERNAL_ERROR",
177
+ [JSON_RPC_ERRORS.METHOD_NOT_FOUND]: "CAPABILITY_NOT_SUPPORTED",
178
+ [JSON_RPC_ERRORS.RESOURCE_NOT_FOUND]: "WALLET_NOT_FOUND",
179
+ [JSON_RPC_ERRORS.RESOURCE_UNAVAILABLE]: "WALLET_NOT_INSTALLED",
180
+ [JSON_RPC_ERRORS.TRANSACTION_REJECTED]: "USER_REJECTED",
181
+ [JSON_RPC_ERRORS.INVALID_INPUT]: "TIMEOUT"
182
+ };
183
+ function toProviderRpcError(err) {
184
+ if (err instanceof ProviderRpcError) {
185
+ return err;
186
+ }
187
+ if (err instanceof core.PartyLayerError) {
188
+ const code = ERROR_CODE_TO_RPC[err.code] ?? JSON_RPC_ERRORS.INTERNAL_ERROR;
189
+ return new ProviderRpcError(err.message, code, {
190
+ originalCode: err.code,
191
+ details: err.details
192
+ });
193
+ }
194
+ if (isRpcShaped(err)) {
195
+ return new ProviderRpcError(err.message, err.code, err.data);
196
+ }
197
+ if (err instanceof Error) {
198
+ return new ProviderRpcError(err.message, JSON_RPC_ERRORS.INTERNAL_ERROR);
199
+ }
200
+ return new ProviderRpcError(String(err), JSON_RPC_ERRORS.INTERNAL_ERROR);
201
+ }
202
+ function toPartyLayerError(err) {
203
+ const code = RPC_TO_ERROR_CODE[err.code] ?? "INTERNAL_ERROR";
204
+ return new core.PartyLayerError(err.message, code, {
205
+ details: { rpcCode: err.code, data: err.data }
206
+ });
207
+ }
208
+ function isRpcShaped(err) {
209
+ if (typeof err !== "object" || err === null) return false;
210
+ const e = err;
211
+ return typeof e.message === "string" && typeof e.code === "number";
212
+ }
213
+
214
+ // src/method-router.ts
215
+ var MethodRouter = class {
216
+ handlers = /* @__PURE__ */ new Map();
217
+ walletProvider = null;
218
+ constructor() {
219
+ this.registerDefaults();
220
+ }
221
+ /** Set / swap the underlying native wallet provider */
222
+ setWalletProvider(provider) {
223
+ this.walletProvider = provider;
224
+ }
225
+ /** Get the current wallet provider */
226
+ getWalletProvider() {
227
+ return this.walletProvider;
228
+ }
229
+ /** Register (or override) a handler for a method name */
230
+ register(method, handler) {
231
+ this.handlers.set(method, handler);
232
+ }
233
+ /** Route a request to the appropriate handler */
234
+ async route(payload) {
235
+ const { method, params } = payload;
236
+ const handler = this.handlers.get(method);
237
+ if (!handler) {
238
+ if (this.walletProvider) {
239
+ try {
240
+ return await this.walletProvider.request(payload);
241
+ } catch (err) {
242
+ throw toProviderRpcError(err);
243
+ }
244
+ }
245
+ throw unsupportedMethod(method);
246
+ }
247
+ if (!this.walletProvider && method !== "connect" && method !== "isConnected") {
248
+ throw disconnected("No wallet provider connected");
249
+ }
250
+ try {
251
+ return await handler(this.walletProvider, params);
252
+ } catch (err) {
253
+ throw toProviderRpcError(err);
254
+ }
255
+ }
256
+ /** Check whether a handler is registered for a given method */
257
+ hasHandler(method) {
258
+ return this.handlers.has(method);
259
+ }
260
+ // ─── Default passthrough handlers ───────────────────────────────────────
261
+ registerDefaults() {
262
+ const passthrough = (method) => {
263
+ return async (wp, params) => {
264
+ return wp.request({ method, params });
265
+ };
266
+ };
267
+ this.register("connect", passthrough("connect"));
268
+ this.register("disconnect", passthrough("disconnect"));
269
+ this.register("isConnected", passthrough("isConnected"));
270
+ this.register("status", passthrough("status"));
271
+ this.register("getActiveNetwork", passthrough("getActiveNetwork"));
272
+ this.register("listAccounts", passthrough("listAccounts"));
273
+ this.register("getPrimaryAccount", passthrough("getPrimaryAccount"));
274
+ this.register("signMessage", passthrough("signMessage"));
275
+ this.register("prepareExecute", passthrough("prepareExecute"));
276
+ this.register("ledgerApi", passthrough("ledgerApi"));
277
+ }
278
+ };
279
+ async function handleAsyncConnect(walletProvider, connectResult, options = {}) {
280
+ if (connectResult.isConnected && !connectResult.userUrl) {
281
+ return connectResult;
282
+ }
283
+ if (connectResult.userUrl) {
284
+ options.onUserUrl?.(connectResult.userUrl);
285
+ }
286
+ const timeoutMs = options.timeoutMs ?? 3e5;
287
+ return new Promise((resolve, reject) => {
288
+ let settled = false;
289
+ const timer = setTimeout(() => {
290
+ if (!settled) {
291
+ settled = true;
292
+ walletProvider.removeListener(core.CIP0103_EVENTS.CONNECTED, onConnected);
293
+ reject(
294
+ new ProviderRpcError(
295
+ "Async connect timed out",
296
+ JSON_RPC_ERRORS.INVALID_INPUT,
297
+ { timeoutMs }
298
+ )
299
+ );
300
+ }
301
+ }, timeoutMs);
302
+ const onConnected = (result) => {
303
+ if (!settled) {
304
+ settled = true;
305
+ clearTimeout(timer);
306
+ walletProvider.removeListener(core.CIP0103_EVENTS.CONNECTED, onConnected);
307
+ resolve(result);
308
+ }
309
+ };
310
+ walletProvider.on(core.CIP0103_EVENTS.CONNECTED, onConnected);
311
+ });
312
+ }
313
+ var TERMINAL_TX_STATUSES = ["executed", "failed"];
314
+ async function handleAsyncPrepareExecute(walletProvider, commandId, userUrl, options = {}) {
315
+ if (userUrl) {
316
+ options.onUserUrl?.(userUrl);
317
+ }
318
+ const timeoutMs = options.timeoutMs ?? 3e5;
319
+ return new Promise((resolve, reject) => {
320
+ let settled = false;
321
+ const timer = setTimeout(() => {
322
+ if (!settled) {
323
+ settled = true;
324
+ walletProvider.removeListener(core.CIP0103_EVENTS.TX_CHANGED, onTxChanged);
325
+ reject(
326
+ new ProviderRpcError(
327
+ "Async prepareExecute timed out",
328
+ JSON_RPC_ERRORS.INVALID_INPUT,
329
+ { commandId, timeoutMs }
330
+ )
331
+ );
332
+ }
333
+ }, timeoutMs);
334
+ const onTxChanged = (event) => {
335
+ if (event.commandId !== commandId) return;
336
+ if (TERMINAL_TX_STATUSES.includes(event.status)) {
337
+ if (!settled) {
338
+ settled = true;
339
+ clearTimeout(timer);
340
+ walletProvider.removeListener(
341
+ core.CIP0103_EVENTS.TX_CHANGED,
342
+ onTxChanged
343
+ );
344
+ if (event.status === "failed") {
345
+ reject(
346
+ new ProviderRpcError(
347
+ "Transaction failed",
348
+ JSON_RPC_ERRORS.TRANSACTION_REJECTED,
349
+ { commandId }
350
+ )
351
+ );
352
+ } else {
353
+ resolve(event);
354
+ }
355
+ }
356
+ }
357
+ };
358
+ walletProvider.on(core.CIP0103_EVENTS.TX_CHANGED, onTxChanged);
359
+ });
360
+ }
361
+
362
+ // src/provider.ts
363
+ var PartyLayerProvider = class {
364
+ eventBus;
365
+ router;
366
+ options;
367
+ nativeProvider;
368
+ connected = false;
369
+ /** Event forwarders from the native provider, keyed by event name */
370
+ nativeForwarders = /* @__PURE__ */ new Map();
371
+ constructor(options = {}) {
372
+ this.options = options;
373
+ this.eventBus = new CIP0103EventBus();
374
+ this.eventBus.setOwner(this);
375
+ this.router = new MethodRouter();
376
+ this.nativeProvider = options.walletProvider?.provider ?? null;
377
+ if (this.nativeProvider) {
378
+ this.router.setWalletProvider(this.nativeProvider);
379
+ this.forwardNativeEvents();
380
+ }
381
+ this.registerOrchestratedMethods();
382
+ }
383
+ // ─── CIP-0103 Provider Interface ─────────────────────────────────────────
384
+ async request(args) {
385
+ return this.router.route(args);
386
+ }
387
+ on(event, listener) {
388
+ this.eventBus.on(event, listener);
389
+ return this;
390
+ }
391
+ emit(event, ...args) {
392
+ return this.eventBus.emit(event, ...args);
393
+ }
394
+ removeListener(event, listenerToRemove) {
395
+ this.eventBus.removeListener(event, listenerToRemove);
396
+ return this;
397
+ }
398
+ // ─── Public Management ────────────────────────────────────────────────────
399
+ /** Whether the provider is currently in a connected state */
400
+ get isConnected() {
401
+ return this.connected;
402
+ }
403
+ /** Switch the underlying wallet provider (e.g. user selects a different wallet) */
404
+ setWalletProvider(discovered) {
405
+ this.unforwardNativeEvents();
406
+ this.nativeProvider = discovered.provider;
407
+ this.router.setWalletProvider(this.nativeProvider);
408
+ this.forwardNativeEvents();
409
+ }
410
+ /** Get the currently attached native provider (if any) */
411
+ getNativeProvider() {
412
+ return this.nativeProvider;
413
+ }
414
+ /** Tear down: unsubscribe all events and release the native provider */
415
+ destroy() {
416
+ this.unforwardNativeEvents();
417
+ this.eventBus.removeAllListeners();
418
+ this.nativeProvider = null;
419
+ this.router.setWalletProvider(null);
420
+ this.connected = false;
421
+ }
422
+ // ─── Orchestrated Method Overrides ────────────────────────────────────────
423
+ registerOrchestratedMethods() {
424
+ this.router.register(
425
+ "connect",
426
+ async (wp, params) => {
427
+ const result = await wp.request({
428
+ method: "connect",
429
+ params
430
+ });
431
+ if (result.userUrl && !result.isConnected) {
432
+ const final = await handleAsyncConnect(wp, result, {
433
+ timeoutMs: this.options.asyncTimeoutMs,
434
+ onUserUrl: this.options.onUserUrl
435
+ });
436
+ this.connected = final.isConnected;
437
+ this.emitStatusChanged();
438
+ return final;
439
+ }
440
+ this.connected = result.isConnected;
441
+ this.emitStatusChanged();
442
+ return result;
443
+ }
444
+ );
445
+ this.router.register("disconnect", async (wp, params) => {
446
+ await wp.request({ method: "disconnect", params });
447
+ this.connected = false;
448
+ this.emitStatusChanged();
449
+ });
450
+ this.router.register(
451
+ "isConnected",
452
+ async (wp, params) => {
453
+ if (!wp) {
454
+ return {
455
+ isConnected: false,
456
+ reason: "No wallet provider connected"
457
+ };
458
+ }
459
+ return wp.request({
460
+ method: "isConnected",
461
+ params
462
+ });
463
+ }
464
+ );
465
+ this.router.register("prepareExecute", async (wp, params) => {
466
+ return wp.request({ method: "prepareExecute", params });
467
+ });
468
+ }
469
+ // ─── Native Event Forwarding ──────────────────────────────────────────────
470
+ forwardNativeEvents() {
471
+ if (!this.nativeProvider) return;
472
+ const eventsToForward = [
473
+ core.CIP0103_EVENTS.STATUS_CHANGED,
474
+ core.CIP0103_EVENTS.ACCOUNTS_CHANGED,
475
+ core.CIP0103_EVENTS.TX_CHANGED,
476
+ core.CIP0103_EVENTS.CONNECTED
477
+ ];
478
+ for (const event of eventsToForward) {
479
+ const forwarder = (...args) => {
480
+ this.eventBus.emit(event, ...args);
481
+ };
482
+ this.nativeForwarders.set(event, forwarder);
483
+ this.nativeProvider.on(event, forwarder);
484
+ }
485
+ }
486
+ unforwardNativeEvents() {
487
+ if (!this.nativeProvider) return;
488
+ for (const [event, forwarder] of this.nativeForwarders) {
489
+ this.nativeProvider.removeListener(event, forwarder);
490
+ }
491
+ this.nativeForwarders.clear();
492
+ }
493
+ // ─── Helpers ──────────────────────────────────────────────────────────────
494
+ /** Emit statusChanged by querying the current wallet provider status */
495
+ async emitStatusChanged() {
496
+ if (!this.nativeProvider) return;
497
+ try {
498
+ const status = await this.nativeProvider.request({
499
+ method: "status"
500
+ });
501
+ this.eventBus.emit(core.CIP0103_EVENTS.STATUS_CHANGED, status);
502
+ } catch {
503
+ }
504
+ }
505
+ };
506
+
507
+ // src/network.ts
508
+ var CANTON_NETWORKS = {
509
+ mainnet: "canton:da-mainnet",
510
+ testnet: "canton:da-testnet",
511
+ devnet: "canton:da-devnet",
512
+ local: "canton:da-local"
513
+ };
514
+ var CAIP2_TO_SHORT = Object.fromEntries(
515
+ Object.entries(CANTON_NETWORKS).map(([short, full]) => [full, short])
516
+ );
517
+ function toCAIP2Network(networkId) {
518
+ let result;
519
+ if (networkId.includes(":")) {
520
+ result = networkId;
521
+ } else {
522
+ const caip2 = CANTON_NETWORKS[networkId];
523
+ result = caip2 ?? `canton:${networkId}`;
524
+ }
525
+ if (!isValidCAIP2(result)) {
526
+ throw new Error(
527
+ `Invalid CAIP-2 network identifier: "${result}". Expected format: "namespace:reference"`
528
+ );
529
+ }
530
+ return { networkId: result };
531
+ }
532
+ function fromCAIP2Network(caip2) {
533
+ const short = CAIP2_TO_SHORT[caip2];
534
+ if (short) return short;
535
+ const colonIndex = caip2.indexOf(":");
536
+ return colonIndex >= 0 ? caip2.slice(colonIndex + 1) : caip2;
537
+ }
538
+ function isValidCAIP2(networkId) {
539
+ return /^[-a-z0-9]{3,8}:[-_a-zA-Z0-9]{1,32}$/.test(networkId);
540
+ }
541
+
542
+ // src/bridge.ts
543
+ var PROVIDER_VERSION = "0.1.1" ;
544
+ function createProviderBridge(client) {
545
+ const eventBus = new CIP0103EventBus();
546
+ const pendingEmitted = /* @__PURE__ */ new Set();
547
+ const bridge = {
548
+ async request(args) {
549
+ return handleRequest(client, args, eventBus, pendingEmitted);
550
+ },
551
+ on(event, listener) {
552
+ eventBus.on(event, listener);
553
+ return bridge;
554
+ },
555
+ emit(event, ...args) {
556
+ return eventBus.emit(event, ...args);
557
+ },
558
+ removeListener(event, listener) {
559
+ eventBus.removeListener(event, listener);
560
+ return bridge;
561
+ }
562
+ };
563
+ eventBus.setOwner(bridge);
564
+ wireEvents(client, eventBus, pendingEmitted);
565
+ return bridge;
566
+ }
567
+ async function handleRequest(client, args, eventBus, pendingEmitted) {
568
+ const { method, params } = args;
569
+ try {
570
+ switch (method) {
571
+ case "connect": {
572
+ await client.connect();
573
+ return {
574
+ isConnected: true
575
+ };
576
+ }
577
+ case "disconnect": {
578
+ await client.disconnect();
579
+ return void 0;
580
+ }
581
+ case "isConnected": {
582
+ const session = await client.getActiveSession();
583
+ return {
584
+ isConnected: session !== null,
585
+ reason: session ? void 0 : "No active session"
586
+ };
587
+ }
588
+ case "status": {
589
+ const session = await client.getActiveSession();
590
+ return {
591
+ connection: {
592
+ isConnected: session !== null
593
+ },
594
+ provider: {
595
+ id: "partylayer",
596
+ version: PROVIDER_VERSION,
597
+ providerType: "browser"
598
+ },
599
+ network: session ? toCAIP2Network(session.network) : void 0,
600
+ session: session ? {
601
+ accessToken: "",
602
+ userId: String(session.partyId)
603
+ } : void 0
604
+ };
605
+ }
606
+ case "getActiveNetwork": {
607
+ const session = await client.getActiveSession();
608
+ return toCAIP2Network(
609
+ session?.network ?? "devnet"
610
+ );
611
+ }
612
+ case "listAccounts": {
613
+ const session = await client.getActiveSession();
614
+ if (!session) return [];
615
+ return [
616
+ sessionToAccount(session)
617
+ ];
618
+ }
619
+ case "getPrimaryAccount": {
620
+ const session = await client.getActiveSession();
621
+ if (!session) throw disconnected("No active session");
622
+ return sessionToAccount(session);
623
+ }
624
+ case "signMessage": {
625
+ const p = normalizeParams(params);
626
+ const result = await client.signMessage({
627
+ message: String(p.message ?? ""),
628
+ nonce: p.nonce ? String(p.nonce) : void 0,
629
+ domain: p.domain ? String(p.domain) : void 0
630
+ });
631
+ return String(result.signature);
632
+ }
633
+ case "prepareExecute": {
634
+ const p = normalizeParams(params);
635
+ const cmdId = `cmd_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`;
636
+ pendingEmitted.add(cmdId);
637
+ eventBus.emit(core.CIP0103_EVENTS.TX_CHANGED, {
638
+ status: "pending",
639
+ commandId: cmdId
640
+ });
641
+ try {
642
+ const signResult = await client.signTransaction({ tx: p });
643
+ const session = await client.getActiveSession();
644
+ const partyId = String(signResult.partyId ?? session?.partyId ?? "unknown");
645
+ eventBus.emit(core.CIP0103_EVENTS.TX_CHANGED, {
646
+ status: "signed",
647
+ commandId: cmdId,
648
+ payload: {
649
+ signature: String(signResult.transactionHash),
650
+ signedBy: partyId,
651
+ party: partyId
652
+ }
653
+ });
654
+ try {
655
+ const receipt = await client.submitTransaction({
656
+ signedTx: signResult.signedTx ?? signResult.transactionHash
657
+ });
658
+ pendingEmitted.delete(cmdId);
659
+ eventBus.emit(core.CIP0103_EVENTS.TX_CHANGED, {
660
+ status: "executed",
661
+ commandId: cmdId,
662
+ payload: {
663
+ updateId: receipt.updateId ?? receipt.commandId ?? String(receipt.transactionHash),
664
+ completionOffset: 0
665
+ }
666
+ });
667
+ } catch (submitErr) {
668
+ pendingEmitted.delete(cmdId);
669
+ eventBus.emit(core.CIP0103_EVENTS.TX_CHANGED, {
670
+ status: "failed",
671
+ commandId: cmdId
672
+ });
673
+ throw submitErr;
674
+ }
675
+ } catch (signErr) {
676
+ if (pendingEmitted.has(cmdId)) {
677
+ pendingEmitted.delete(cmdId);
678
+ eventBus.emit(core.CIP0103_EVENTS.TX_CHANGED, {
679
+ status: "failed",
680
+ commandId: cmdId
681
+ });
682
+ }
683
+ throw signErr;
684
+ }
685
+ return void 0;
686
+ }
687
+ case "ledgerApi": {
688
+ if (!client.ledgerApi) {
689
+ throw unsupportedMethod("ledgerApi");
690
+ }
691
+ const p = normalizeParams(params);
692
+ const result = await client.ledgerApi({
693
+ requestMethod: String(p.requestMethod ?? "GET"),
694
+ resource: String(p.resource ?? ""),
695
+ body: p.body ? String(p.body) : void 0
696
+ });
697
+ return result;
698
+ }
699
+ default:
700
+ throw unsupportedMethod(method);
701
+ }
702
+ } catch (err) {
703
+ throw toProviderRpcError(err);
704
+ }
705
+ }
706
+ function wireEvents(client, eventBus, pendingEmitted) {
707
+ client.on("session:connected", (event) => {
708
+ const e = event;
709
+ if (!e || typeof e !== "object" || !("session" in e)) return;
710
+ const session = e.session;
711
+ eventBus.emit(core.CIP0103_EVENTS.STATUS_CHANGED, {
712
+ connection: { isConnected: true },
713
+ provider: {
714
+ id: "partylayer",
715
+ version: PROVIDER_VERSION,
716
+ providerType: "browser"
717
+ },
718
+ network: toCAIP2Network(session.network),
719
+ session: {
720
+ accessToken: "",
721
+ userId: String(session.partyId)
722
+ }
723
+ });
724
+ eventBus.emit(core.CIP0103_EVENTS.ACCOUNTS_CHANGED, [
725
+ {
726
+ primary: true,
727
+ partyId: String(session.partyId),
728
+ status: "allocated",
729
+ hint: "",
730
+ publicKey: "",
731
+ namespace: "",
732
+ networkId: toCAIP2Network(session.network).networkId,
733
+ signingProviderId: ""
734
+ }
735
+ ]);
736
+ eventBus.emit(core.CIP0103_EVENTS.CONNECTED, {
737
+ isConnected: true
738
+ });
739
+ });
740
+ client.on("session:disconnected", () => {
741
+ eventBus.emit(core.CIP0103_EVENTS.STATUS_CHANGED, {
742
+ connection: { isConnected: false },
743
+ provider: {
744
+ id: "partylayer",
745
+ version: PROVIDER_VERSION,
746
+ providerType: "browser"
747
+ }
748
+ });
749
+ });
750
+ client.on("tx:status", (event) => {
751
+ const e = event;
752
+ if (!e || typeof e !== "object" || !("status" in e)) return;
753
+ const statusMap = {
754
+ pending: "pending",
755
+ submitted: "pending",
756
+ signed: "signed",
757
+ committed: "executed",
758
+ rejected: "failed",
759
+ failed: "failed"
760
+ };
761
+ const mappedStatus = statusMap[e.status] ?? "pending";
762
+ const commandId = String(e.txId);
763
+ if (mappedStatus === "pending" && pendingEmitted.has(commandId)) {
764
+ return;
765
+ }
766
+ if (mappedStatus === "executed" || mappedStatus === "failed") {
767
+ pendingEmitted.delete(commandId);
768
+ }
769
+ let txEvent;
770
+ switch (mappedStatus) {
771
+ case "signed":
772
+ txEvent = {
773
+ status: "signed",
774
+ commandId,
775
+ payload: {
776
+ signature: "",
777
+ signedBy: "",
778
+ party: ""
779
+ }
780
+ };
781
+ break;
782
+ case "executed": {
783
+ const raw = e.raw;
784
+ txEvent = {
785
+ status: "executed",
786
+ commandId,
787
+ payload: {
788
+ updateId: raw?.updateId ?? raw?.commandId ?? commandId,
789
+ completionOffset: 0
790
+ }
791
+ };
792
+ break;
793
+ }
794
+ case "failed":
795
+ txEvent = { status: "failed", commandId };
796
+ break;
797
+ default:
798
+ txEvent = { status: "pending", commandId };
799
+ break;
800
+ }
801
+ eventBus.emit(core.CIP0103_EVENTS.TX_CHANGED, txEvent);
802
+ });
803
+ }
804
+ function normalizeParams(params) {
805
+ if (!params) return {};
806
+ if (Array.isArray(params)) return params[0] ?? {};
807
+ return params;
808
+ }
809
+ function sessionToAccount(session) {
810
+ return {
811
+ primary: true,
812
+ partyId: String(session.partyId),
813
+ status: "allocated",
814
+ hint: "",
815
+ publicKey: "",
816
+ namespace: "",
817
+ networkId: toCAIP2Network(session.network).networkId,
818
+ signingProviderId: ""
819
+ };
820
+ }
821
+
822
+ // src/discovery.ts
823
+ var KNOWN_INJECTION_PATHS = [
824
+ "canton",
825
+ "cantonWallet",
826
+ "consoleWallet",
827
+ "splice"
828
+ ];
829
+ function isCIP0103Provider(obj) {
830
+ if (typeof obj !== "object" || obj === null) return false;
831
+ const p = obj;
832
+ return typeof p.request === "function" && typeof p.on === "function" && typeof p.emit === "function" && typeof p.removeListener === "function";
833
+ }
834
+ function discoverInjectedProviders() {
835
+ if (typeof window === "undefined") return [];
836
+ const discovered = [];
837
+ const seen = /* @__PURE__ */ new Set();
838
+ const win = window;
839
+ for (const path of KNOWN_INJECTION_PATHS) {
840
+ const candidate = win[path];
841
+ if (candidate === void 0 || candidate === null) continue;
842
+ if (isCIP0103Provider(candidate) && !seen.has(candidate)) {
843
+ seen.add(candidate);
844
+ discovered.push({
845
+ id: path,
846
+ provider: candidate,
847
+ source: "injected"
848
+ });
849
+ continue;
850
+ }
851
+ if (typeof candidate === "object") {
852
+ for (const [key, value] of Object.entries(
853
+ candidate
854
+ )) {
855
+ if (isCIP0103Provider(value) && !seen.has(value)) {
856
+ seen.add(value);
857
+ discovered.push({
858
+ id: `${path}.${key}`,
859
+ provider: value,
860
+ source: "injected"
861
+ });
862
+ }
863
+ }
864
+ }
865
+ }
866
+ return discovered;
867
+ }
868
+ function waitForProvider(id, timeoutMs = 3e3) {
869
+ return new Promise((resolve) => {
870
+ const match = findById(id);
871
+ if (match) {
872
+ resolve(match);
873
+ return;
874
+ }
875
+ const start = Date.now();
876
+ const interval = setInterval(() => {
877
+ const match2 = findById(id);
878
+ if (match2) {
879
+ clearInterval(interval);
880
+ resolve(match2);
881
+ return;
882
+ }
883
+ if (Date.now() - start >= timeoutMs) {
884
+ clearInterval(interval);
885
+ resolve(null);
886
+ }
887
+ }, 100);
888
+ });
889
+ }
890
+ function findById(id) {
891
+ return discoverInjectedProviders().find(
892
+ (p) => p.id === id || p.id.endsWith(`.${id}`)
893
+ );
894
+ }
895
+
896
+ Object.defineProperty(exports, "CIP0103_EVENTS", {
897
+ enumerable: true,
898
+ get: function () { return core.CIP0103_EVENTS; }
899
+ });
900
+ Object.defineProperty(exports, "CIP0103_MANDATORY_METHODS", {
901
+ enumerable: true,
902
+ get: function () { return core.CIP0103_MANDATORY_METHODS; }
903
+ });
904
+ Object.defineProperty(exports, "CIP0103_METHODS", {
905
+ enumerable: true,
906
+ get: function () { return core.CIP0103_METHODS; }
907
+ });
908
+ exports.CANTON_NETWORKS = CANTON_NETWORKS;
909
+ exports.CIP0103EventBus = CIP0103EventBus;
910
+ exports.JSON_RPC_ERRORS = JSON_RPC_ERRORS;
911
+ exports.MethodRouter = MethodRouter;
912
+ exports.PartyLayerProvider = PartyLayerProvider;
913
+ exports.ProviderRpcError = ProviderRpcError;
914
+ exports.RPC_ERRORS = RPC_ERRORS;
915
+ exports.chainDisconnected = chainDisconnected;
916
+ exports.createProviderBridge = createProviderBridge;
917
+ exports.disconnected = disconnected;
918
+ exports.discoverInjectedProviders = discoverInjectedProviders;
919
+ exports.fromCAIP2Network = fromCAIP2Network;
920
+ exports.handleAsyncConnect = handleAsyncConnect;
921
+ exports.handleAsyncPrepareExecute = handleAsyncPrepareExecute;
922
+ exports.internalError = internalError;
923
+ exports.invalidParams = invalidParams;
924
+ exports.isCIP0103Provider = isCIP0103Provider;
925
+ exports.isValidCAIP2 = isValidCAIP2;
926
+ exports.methodNotFound = methodNotFound;
927
+ exports.resourceNotFound = resourceNotFound;
928
+ exports.resourceUnavailable = resourceUnavailable;
929
+ exports.toCAIP2Network = toCAIP2Network;
930
+ exports.toPartyLayerError = toPartyLayerError;
931
+ exports.toProviderRpcError = toProviderRpcError;
932
+ exports.transactionRejected = transactionRejected;
933
+ exports.unauthorized = unauthorized;
934
+ exports.unsupportedMethod = unsupportedMethod;
935
+ exports.userRejected = userRejected;
936
+ exports.waitForProvider = waitForProvider;
937
+ //# sourceMappingURL=index.js.map
938
+ //# sourceMappingURL=index.js.map