@partylayer/adapter-cantor8 0.2.20 → 0.3.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/index.mjs CHANGED
@@ -1,311 +1,177 @@
1
- import { toWalletId, MockTransport, DeepLinkTransport, UserRejectedError, mapUnknownErrorToPartyLayerError, toSignature, toTransactionHash, toPartyId } from '@partylayer/core';
1
+ import { toWalletId, toPartyId, mapUnknownErrorToPartyLayerError, CapabilityNotSupportedError, toTransactionHash } from '@partylayer/core';
2
2
 
3
3
  // src/cantor8-adapter.ts
4
- var StubCantor8VendorModule = class {
5
- createConnectUrl(request, config) {
6
- if (config.universalLinkBase) {
7
- const endpoint = config.connectEndpoint || "/connect";
8
- const url = new URL(endpoint, config.universalLinkBase);
9
- Object.entries(request).forEach(([key, value]) => {
10
- if (value !== void 0) {
11
- url.searchParams.set(key, typeof value === "string" ? value : JSON.stringify(value));
12
- }
13
- });
14
- return url.toString();
15
- }
16
- if (config.deepLinkScheme) {
17
- const params = new URLSearchParams();
18
- Object.entries(request).forEach(([key, value]) => {
19
- if (value !== void 0) {
20
- params.set(key, typeof value === "string" ? value : JSON.stringify(value));
21
- }
22
- });
23
- return `${config.deepLinkScheme}://connect?${params.toString()}`;
24
- }
25
- throw new Error(
26
- "Cantor8 vendor not configured. Please set deepLinkScheme or universalLinkBase in adapter config."
27
- );
4
+ var c8ModulePromise = null;
5
+ function loadC8() {
6
+ if (!c8ModulePromise) {
7
+ c8ModulePromise = import('@cantor8/wallet-connect-sdk');
28
8
  }
29
- parseConnectCallback(callbackData, expectedState) {
30
- const data = callbackData;
31
- if (data.state !== expectedState) {
32
- throw new Error("State mismatch in callback");
33
- }
34
- return {
35
- state: String(data.state),
36
- partyId: data.partyId ? toPartyId(String(data.partyId)) : void 0,
37
- sessionToken: data.sessionToken ? String(data.sessionToken) : void 0,
38
- expiresAt: data.expiresAt ? Number(data.expiresAt) : void 0,
39
- capabilities: data.capabilities ? Array.isArray(data.capabilities) ? data.capabilities.map(String) : [] : void 0,
40
- error: data.error ? {
41
- code: String(data.error.code || "UNKNOWN"),
42
- message: String(data.error.message || "Unknown error")
43
- } : void 0
44
- };
45
- }
46
- createSignUrl(request, config) {
47
- if (config.universalLinkBase) {
48
- const endpoint = config.signEndpoint || "/sign";
49
- const url = new URL(endpoint, config.universalLinkBase);
50
- Object.entries(request).forEach(([key, value]) => {
51
- if (value !== void 0) {
52
- url.searchParams.set(key, typeof value === "string" ? value : JSON.stringify(value));
53
- }
54
- });
55
- return url.toString();
56
- }
57
- if (config.deepLinkScheme) {
58
- const params = new URLSearchParams();
59
- Object.entries(request).forEach(([key, value]) => {
60
- if (value !== void 0) {
61
- params.set(key, typeof value === "string" ? value : JSON.stringify(value));
62
- }
63
- });
64
- return `${config.deepLinkScheme}://sign?${params.toString()}`;
65
- }
66
- throw new Error("Cantor8 vendor not configured");
67
- }
68
- parseSignCallback(callbackData, expectedState) {
69
- const data = callbackData;
70
- if (data.state !== expectedState) {
71
- throw new Error("State mismatch in callback");
72
- }
73
- return {
74
- state: String(data.state),
75
- signature: data.signature ? String(data.signature) : void 0,
76
- transactionHash: data.transactionHash ? String(data.transactionHash) : void 0,
77
- jobId: data.jobId ? String(data.jobId) : void 0,
78
- error: data.error ? {
79
- code: String(data.error.code || "UNKNOWN"),
80
- message: String(data.error.message || "Unknown error")
81
- } : void 0
82
- };
83
- }
84
- };
85
-
86
- // src/cantor8-adapter.ts
9
+ return c8ModulePromise;
10
+ }
87
11
  var Cantor8Adapter = class {
88
12
  walletId = toWalletId("cantor8");
89
13
  name = "Cantor8";
90
- vendorModule;
91
- vendorConfig;
92
- transport;
14
+ config;
15
+ provider = null;
93
16
  constructor(config = {}) {
94
- this.vendorModule = config.vendorModule || new StubCantor8VendorModule();
95
- this.vendorConfig = config.vendorConfig || {};
96
- if (config.useMockTransport || process.env.NODE_ENV === "development") {
97
- this.transport = new MockTransport();
98
- } else {
99
- this.transport = new DeepLinkTransport();
100
- }
17
+ this.config = config;
101
18
  }
102
19
  getCapabilities() {
103
- return [
104
- "connect",
105
- "disconnect",
106
- "restore",
107
- "deeplink",
108
- "signMessage",
109
- "signTransaction"
110
- ];
20
+ return ["connect", "disconnect", "submitTransaction", "events", "popup"];
21
+ }
22
+ /** The SDK supports devnet and mainnet only; anything else fails at connect. */
23
+ mapNetwork(network) {
24
+ if (network === "devnet") return "devnet";
25
+ if (network === "mainnet") return "mainnet";
26
+ throw new Error(
27
+ `Cantor8 does not support the "${network}" network (supported: devnet, mainnet).`
28
+ );
111
29
  }
112
- detectInstalled() {
30
+ async detectInstalled() {
113
31
  if (typeof window === "undefined") {
114
- return Promise.resolve({ installed: false, reason: "Browser environment required" });
32
+ return { installed: false, reason: "Browser environment required" };
115
33
  }
116
- const isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
117
- return Promise.resolve({
118
- installed: isMobile,
119
- reason: isMobile ? void 0 : "Cantor8 is a mobile wallet"
34
+ const { onC8ProviderDiscovered } = await loadC8();
35
+ const timeoutMs = this.config.detectTimeoutMs ?? 300;
36
+ return new Promise((resolve) => {
37
+ let settled = false;
38
+ const state = {};
39
+ const finish = (result) => {
40
+ if (settled) return;
41
+ settled = true;
42
+ clearTimeout(timer);
43
+ try {
44
+ state.unsubscribe?.();
45
+ } catch {
46
+ }
47
+ resolve(result);
48
+ };
49
+ const timer = setTimeout(
50
+ () => finish({
51
+ installed: false,
52
+ reason: "Cantor8 wallet did not announce (no c8#provider_discovery event)"
53
+ }),
54
+ timeoutMs
55
+ );
56
+ state.unsubscribe = onC8ProviderDiscovered(() => finish({ installed: true }));
120
57
  });
121
58
  }
122
- async connect(ctx, opts) {
59
+ async connect(ctx, _opts) {
123
60
  try {
124
- const state = this.generateState();
125
- const redirectUri = this.vendorConfig.redirectUri || `${ctx.origin}/callback`;
126
- const request = {
127
- appName: ctx.appName,
128
- origin: ctx.origin,
129
- network: ctx.network,
130
- requestedCapabilities: void 0,
131
- // Cantor8 doesn't support capability filtering yet
132
- state,
133
- redirectUri
134
- };
135
- const connectUrl = this.vendorModule.createConnectUrl(request, this.vendorConfig);
136
- const transportOptions = {
137
- timeoutMs: opts?.timeoutMs || 6e4,
138
- allowedOrigins: [ctx.origin],
139
- origin: ctx.origin
140
- };
141
- const response = await this.transport.openConnectRequest(
142
- connectUrl,
143
- request,
144
- transportOptions
145
- );
146
- if (response.error) {
147
- if (response.error.code === "USER_REJECTED" || response.error.code === "CANCELLED") {
148
- throw new UserRejectedError("User rejected connection");
149
- }
150
- throw new Error(response.error.message || "Connection failed");
151
- }
152
- if (!response.partyId) {
153
- throw new Error("No partyId in response");
61
+ const { C8WalletProvider } = await loadC8();
62
+ const provider = new C8WalletProvider({
63
+ dappName: ctx.appName,
64
+ dappUrl: this.config.dappUrl ?? ctx.origin,
65
+ network: this.mapNetwork(ctx.network)
66
+ });
67
+ await provider.connect();
68
+ const { accounts } = await provider.getAccounts();
69
+ const partyId = accounts?.[0]?.partyId;
70
+ if (!partyId) {
71
+ throw new Error("Cantor8 returned no account after connect");
154
72
  }
73
+ this.provider = provider;
155
74
  return {
156
- partyId: response.partyId,
75
+ partyId: toPartyId(partyId),
157
76
  session: {
158
77
  walletId: this.walletId,
159
- // Cantor8's connect response carries no network → not wallet-reported,
160
- // so network-mismatch detection is limited for this adapter (echoes
161
- // the requested ctx.network).
78
+ // Cantor8's connect carries no network → echo the requested one.
162
79
  network: ctx.network,
163
- createdAt: Date.now(),
164
- expiresAt: response.expiresAt,
165
- capabilitiesSnapshot: response.capabilities || ["connect", "signMessage"],
166
- metadata: {
167
- sessionToken: response.sessionToken || ""
168
- }
80
+ createdAt: Date.now()
169
81
  },
170
- capabilities: response.capabilities || ["connect", "signMessage"]
82
+ capabilities: this.getCapabilities()
171
83
  };
172
84
  } catch (err) {
173
85
  throw mapUnknownErrorToPartyLayerError(err, {
174
86
  walletId: this.walletId,
175
87
  phase: "connect",
176
- transport: "deeplink"
88
+ transport: "popup"
177
89
  });
178
90
  }
179
91
  }
180
- disconnect(_ctx, _session) {
181
- if (_session.metadata?.sessionToken) ;
182
- return Promise.resolve();
183
- }
184
- restore(_ctx, persisted) {
185
- const sessionToken = persisted.metadata?.sessionToken;
186
- if (typeof sessionToken !== "string") {
187
- return Promise.resolve(null);
188
- }
189
- if (persisted.expiresAt && Date.now() >= persisted.expiresAt) {
190
- return Promise.resolve(null);
191
- }
192
- return Promise.resolve({
193
- ...persisted,
194
- walletId: this.walletId
195
- });
196
- }
197
- async signMessage(ctx, session, params) {
92
+ async disconnect(_ctx, _session) {
93
+ if (!this.provider) return;
198
94
  try {
199
- const state = this.generateState();
200
- const redirectUri = this.vendorConfig.redirectUri || `${ctx.origin}/callback`;
201
- const request = {
202
- message: params.message,
203
- state,
204
- redirectUri
205
- };
206
- const signUrl = this.vendorModule.createSignUrl(request, this.vendorConfig);
207
- const transportOptions = {
208
- timeoutMs: 6e4,
209
- allowedOrigins: [ctx.origin],
210
- origin: ctx.origin
211
- };
212
- const response = await this.transport.openSignRequest(
213
- signUrl,
214
- request,
215
- transportOptions
216
- );
217
- if (response.error) {
218
- if (response.error.code === "USER_REJECTED") {
219
- throw new UserRejectedError("User rejected signing");
220
- }
221
- throw new Error(response.error.message || "Signing failed");
222
- }
223
- if (!response.signature) {
224
- throw new Error("No signature in response");
225
- }
226
- return {
227
- message: params.message,
228
- signature: toSignature(response.signature),
229
- partyId: session.partyId
230
- };
231
- } catch (err) {
232
- throw mapUnknownErrorToPartyLayerError(err, {
233
- walletId: this.walletId,
234
- phase: "signMessage",
235
- transport: "deeplink"
236
- });
95
+ await this.provider.disconnect();
96
+ } finally {
97
+ this.provider = null;
237
98
  }
238
99
  }
239
- async signTransaction(ctx, session, params) {
100
+ /**
101
+ * Cantor8 has NO arbitrary-message signing. Per the honesty rule: do not
102
+ * simulate it, do not route it through `signAndExecute` (which is for
103
+ * transactions), and do not silently succeed. Fail with the typed capability
104
+ * error. `signMessage` is also absent from `getCapabilities()`, so the SDK's
105
+ * capability guard blocks it first; this is the belt-and-suspenders backstop.
106
+ */
107
+ signMessage(_ctx, _session, _params) {
108
+ return Promise.reject(
109
+ new CapabilityNotSupportedError(String(this.walletId), "signMessage")
110
+ );
111
+ }
112
+ /**
113
+ * Submit a transaction through the SDK's `signAndExecute` (sign + execute
114
+ * fused; the wallet has no separate sign step). `params.signedTx` is passed
115
+ * through: the caller owns its shape, which must be a {@link Cantor8SubmitPayload}.
116
+ *
117
+ * The SDK's `signAndExecute` resolves with no id; Cantor8 delivers the
118
+ * on-ledger txId and status asynchronously via the `txChanged` event (surfaced
119
+ * through `on('txStatus')`). The receipt is therefore keyed on the
120
+ * caller-supplied `commandId`; the confirmed ledger id arrives on the event
121
+ * stream. A live run against the real wallet is required to confirm
122
+ * end-to-end execution.
123
+ */
124
+ async submitTransaction(_ctx, _session, params) {
240
125
  try {
241
- const state = this.generateState();
242
- const redirectUri = this.vendorConfig.redirectUri || `${ctx.origin}/callback`;
243
- const request = {
244
- transaction: params.tx,
245
- state,
246
- redirectUri
247
- };
248
- const signUrl = this.vendorModule.createSignUrl(request, this.vendorConfig);
249
- const transportOptions = {
250
- timeoutMs: 6e4,
251
- allowedOrigins: [ctx.origin],
252
- origin: ctx.origin
253
- };
254
- const response = await this.transport.openSignRequest(
255
- signUrl,
256
- request,
257
- transportOptions
258
- );
259
- if (response.error) {
260
- if (response.error.code === "USER_REJECTED") {
261
- throw new UserRejectedError("User rejected signing");
262
- }
263
- throw new Error(response.error.message || "Signing failed");
126
+ if (!this.provider) {
127
+ throw new Error("Not connected to Cantor8");
264
128
  }
265
- if (response.jobId && this.vendorModule.pollJobStatus) {
266
- const statusUrl = this.vendorConfig.statusEndpoint || "";
267
- const jobStatus = await this.vendorModule.pollJobStatus(
268
- response.jobId,
269
- statusUrl,
270
- 6e4
129
+ const input = params.signedTx;
130
+ if (!input || typeof input.commandId !== "string" || typeof input.commandsJson !== "string" || typeof input.partyId !== "string") {
131
+ throw new Error(
132
+ "Cantor8 submitTransaction requires signedTx to be the SDK signAndExecute input { note?, partyId, commandId, commandsJson, disclosedContracts? }."
271
133
  );
272
- if (jobStatus.status === "denied") {
273
- throw new UserRejectedError("Transaction signing denied");
274
- }
275
- if (jobStatus.status === "approved" && jobStatus.result?.signature) {
276
- const signedTx2 = typeof params.tx === "object" && params.tx !== null ? { ...params.tx, signature: jobStatus.result.signature } : { tx: params.tx, signature: jobStatus.result.signature };
277
- return {
278
- signedTx: signedTx2,
279
- transactionHash: jobStatus.result.transactionHash ? toTransactionHash(jobStatus.result.transactionHash) : toTransactionHash("pending"),
280
- partyId: session.partyId
281
- };
282
- }
283
- throw new Error("Job not completed");
284
- }
285
- if (!response.signature) {
286
- throw new Error("No signature in response");
287
134
  }
288
- const signedTx = typeof params.tx === "object" && params.tx !== null ? { ...params.tx, signature: response.signature } : { tx: params.tx, signature: response.signature };
135
+ await this.provider.signAndExecute({
136
+ note: input.note ?? "",
137
+ partyId: input.partyId,
138
+ commandId: input.commandId,
139
+ commandsJson: input.commandsJson,
140
+ disclosedContracts: input.disclosedContracts ?? ""
141
+ });
289
142
  return {
290
- signedTx,
291
- transactionHash: response.transactionHash ? toTransactionHash(response.transactionHash) : toTransactionHash("pending"),
292
- partyId: session.partyId
143
+ transactionHash: toTransactionHash(input.commandId),
144
+ submittedAt: Date.now(),
145
+ commandId: input.commandId
293
146
  };
294
147
  } catch (err) {
295
148
  throw mapUnknownErrorToPartyLayerError(err, {
296
149
  walletId: this.walletId,
297
- phase: "signTransaction",
298
- transport: "deeplink"
150
+ phase: "submitTransaction",
151
+ transport: "popup"
299
152
  });
300
153
  }
301
154
  }
302
155
  /**
303
- * Generate random state nonce
156
+ * Forward the wallet's transaction-status stream. Cantor8 emits `txChanged`
157
+ * ({ txId, status }); PartyLayer surfaces this as the `events` capability under
158
+ * the `txStatus` event. Any other event name is a no-op. Returns an
159
+ * unsubscribe function.
304
160
  */
305
- generateState() {
306
- const array = new Uint8Array(32);
307
- crypto.getRandomValues(array);
308
- return Array.from(array, (byte) => byte.toString(16).padStart(2, "0")).join("");
161
+ on(event, handler) {
162
+ if (event !== "txStatus" || !this.provider) {
163
+ return () => {
164
+ };
165
+ }
166
+ const off = this.provider.on("txChanged", (e) => {
167
+ handler({ txId: e.txId, status: e.status });
168
+ });
169
+ return () => {
170
+ try {
171
+ off();
172
+ } catch {
173
+ }
174
+ };
309
175
  }
310
176
  };
311
177
 
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/vendor.ts","../src/cantor8-adapter.ts"],"names":["signedTx"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * Cantor8 Vendor Integration Module\n * \n * This module abstracts vendor-specific endpoints and can be swapped\n * without breaking the adapter API.\n * \n * References:\n * - Cantor8 ecosystem: https://www.canton.network/ecosystem/cantor8\n * - Cantor8 site: https://cantor8.tech/about\n */\n\nimport type {\n ConnectRequest,\n ConnectResponse,\n SignRequest,\n SignResponse,\n JobStatus,\n} from '@partylayer/core';\nimport { toPartyId } from '@partylayer/core';\n\n/**\n * Vendor configuration\n */\nexport interface Cantor8VendorConfig {\n /** Deep link scheme (e.g., \"cantor8\") */\n deepLinkScheme?: string;\n /** Universal link base URL (e.g., \"https://app.cantor8.tech\") */\n universalLinkBase?: string;\n /** Connect endpoint path */\n connectEndpoint?: string;\n /** Sign endpoint path */\n signEndpoint?: string;\n /** Job status endpoint path (for async approvals) */\n statusEndpoint?: string;\n /** Redirect URI for callbacks */\n redirectUri?: string;\n}\n\n/**\n * Vendor module interface\n * \n * Implementations can be swapped without changing adapter code.\n */\nexport interface Cantor8VendorModule {\n /**\n * Create connect URL\n */\n createConnectUrl(request: ConnectRequest, config: Cantor8VendorConfig): string;\n\n /**\n * Parse connect callback\n */\n parseConnectCallback(\n callbackData: unknown,\n expectedState: string\n ): ConnectResponse;\n\n /**\n * Create sign URL\n */\n createSignUrl(request: SignRequest, config: Cantor8VendorConfig): string;\n\n /**\n * Parse sign callback\n */\n parseSignCallback(\n callbackData: unknown,\n expectedState: string\n ): SignResponse;\n\n /**\n * Poll job status (optional, for async approvals)\n */\n pollJobStatus?(\n jobId: string,\n statusUrl: string,\n timeoutMs: number\n ): Promise<JobStatus>;\n}\n\n/**\n * Default/stub vendor module\n * \n * This implementation provides a structured interface but throws\n * NotConfiguredError with clear instructions when vendor endpoints\n * are not configured.\n */\nexport class StubCantor8VendorModule implements Cantor8VendorModule {\n createConnectUrl(request: ConnectRequest, config: Cantor8VendorConfig): string {\n // Prefer universal link if configured\n if (config.universalLinkBase) {\n const endpoint = config.connectEndpoint || '/connect';\n const url = new URL(endpoint, config.universalLinkBase);\n Object.entries(request).forEach(([key, value]) => {\n if (value !== undefined) {\n url.searchParams.set(key, typeof value === 'string' ? value : JSON.stringify(value));\n }\n });\n return url.toString();\n }\n\n // Fallback to deep link scheme\n if (config.deepLinkScheme) {\n const params = new URLSearchParams();\n Object.entries(request).forEach(([key, value]) => {\n if (value !== undefined) {\n params.set(key, typeof value === 'string' ? value : JSON.stringify(value));\n }\n });\n return `${config.deepLinkScheme}://connect?${params.toString()}`;\n }\n\n throw new Error(\n 'Cantor8 vendor not configured. Please set deepLinkScheme or universalLinkBase in adapter config.'\n );\n }\n\n parseConnectCallback(\n callbackData: unknown,\n expectedState: string\n ): ConnectResponse {\n // Parse callback data (could be URL params, postMessage, etc.)\n const data = callbackData as Record<string, unknown>;\n\n // Validate state\n if (data.state !== expectedState) {\n throw new Error('State mismatch in callback');\n }\n\n // Return response\n return {\n state: String(data.state),\n partyId: data.partyId ? toPartyId(String(data.partyId)) : undefined,\n sessionToken: data.sessionToken ? String(data.sessionToken) : undefined,\n expiresAt: data.expiresAt ? Number(data.expiresAt) : undefined,\n capabilities: data.capabilities\n ? (Array.isArray(data.capabilities) ? data.capabilities.map(String) : [])\n : undefined,\n error: data.error\n ? {\n code: String((data.error as Record<string, unknown>).code || 'UNKNOWN'),\n message: String((data.error as Record<string, unknown>).message || 'Unknown error'),\n }\n : undefined,\n };\n }\n\n createSignUrl(request: SignRequest, config: Cantor8VendorConfig): string {\n if (config.universalLinkBase) {\n const endpoint = config.signEndpoint || '/sign';\n const url = new URL(endpoint, config.universalLinkBase);\n Object.entries(request).forEach(([key, value]) => {\n if (value !== undefined) {\n url.searchParams.set(key, typeof value === 'string' ? value : JSON.stringify(value));\n }\n });\n return url.toString();\n }\n\n if (config.deepLinkScheme) {\n const params = new URLSearchParams();\n Object.entries(request).forEach(([key, value]) => {\n if (value !== undefined) {\n params.set(key, typeof value === 'string' ? value : JSON.stringify(value));\n }\n });\n return `${config.deepLinkScheme}://sign?${params.toString()}`;\n }\n\n throw new Error('Cantor8 vendor not configured');\n }\n\n parseSignCallback(\n callbackData: unknown,\n expectedState: string\n ): SignResponse {\n const data = callbackData as Record<string, unknown>;\n\n if (data.state !== expectedState) {\n throw new Error('State mismatch in callback');\n }\n\n return {\n state: String(data.state),\n signature: data.signature ? String(data.signature) : undefined,\n transactionHash: data.transactionHash ? String(data.transactionHash) : undefined,\n jobId: data.jobId ? String(data.jobId) : undefined,\n error: data.error\n ? {\n code: String((data.error as Record<string, unknown>).code || 'UNKNOWN'),\n message: String((data.error as Record<string, unknown>).message || 'Unknown error'),\n }\n : undefined,\n };\n }\n}\n","/**\n * Cantor8 (C8) Wallet Adapter\n * \n * Implements WalletAdapter interface for Cantor8 wallet using deep link transport.\n * \n * References:\n * - Cantor8 ecosystem: https://www.canton.network/ecosystem/cantor8\n * - Cantor8 site: https://cantor8.tech/about\n * - Wallet Integration Guide: https://docs.digitalasset.com/integrate/devnet/index.html\n */\n\nimport type {\n WalletAdapter,\n AdapterContext,\n AdapterDetectResult,\n AdapterConnectResult,\n SignMessageParams,\n SignTransactionParams,\n} from '@partylayer/core';\nimport {\n toWalletId,\n toSignature,\n toTransactionHash,\n UserRejectedError,\n mapUnknownErrorToPartyLayerError,\n type CapabilityKey,\n} from '@partylayer/core';\nimport { DeepLinkTransport, MockTransport } from '@partylayer/core';\nimport type {\n Cantor8VendorModule,\n Cantor8VendorConfig,\n} from './vendor';\nimport {\n StubCantor8VendorModule,\n} from './vendor';\n\n/**\n * Cantor8 adapter configuration\n */\nexport interface Cantor8AdapterConfig {\n /** Vendor module (defaults to stub) */\n vendorModule?: Cantor8VendorModule;\n /** Vendor configuration */\n vendorConfig?: Cantor8VendorConfig;\n /** Use mock transport in development */\n useMockTransport?: boolean;\n}\n\n/**\n * Cantor8 Wallet Adapter\n */\nexport class Cantor8Adapter implements WalletAdapter {\n readonly walletId = toWalletId('cantor8');\n readonly name = 'Cantor8';\n\n private vendorModule: Cantor8VendorModule;\n private vendorConfig: Cantor8VendorConfig;\n private transport: DeepLinkTransport | MockTransport;\n\n constructor(config: Cantor8AdapterConfig = {}) {\n this.vendorModule = config.vendorModule || new StubCantor8VendorModule();\n this.vendorConfig = config.vendorConfig || {};\n \n // Use mock transport in development if configured\n if (config.useMockTransport || process.env.NODE_ENV === 'development') {\n this.transport = new MockTransport();\n } else {\n this.transport = new DeepLinkTransport();\n }\n }\n\n getCapabilities(): CapabilityKey[] {\n return [\n 'connect',\n 'disconnect',\n 'restore',\n 'deeplink',\n 'signMessage',\n 'signTransaction',\n ];\n }\n\n detectInstalled(): Promise<AdapterDetectResult> {\n // Cantor8 is a mobile wallet - detection is not straightforward\n // We can check for deep link support or user agent hints\n if (typeof window === 'undefined') {\n return Promise.resolve({ installed: false, reason: 'Browser environment required' });\n }\n\n // Check if device supports deep links (mobile)\n const isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);\n \n // For now, assume installed if mobile device\n // In production, might check for specific user agent or other hints\n return Promise.resolve({\n installed: isMobile,\n reason: isMobile ? undefined : 'Cantor8 is a mobile wallet',\n });\n }\n\n async connect(\n ctx: AdapterContext,\n opts?: {\n timeoutMs?: number;\n partyId?: import('@partylayer/core').PartyId;\n }\n ): Promise<AdapterConnectResult> {\n try {\n // Create connect request\n const state = this.generateState();\n const redirectUri = this.vendorConfig.redirectUri || `${ctx.origin}/callback`;\n const request: import('@partylayer/core').ConnectRequest = {\n appName: ctx.appName,\n origin: ctx.origin,\n network: ctx.network,\n requestedCapabilities: undefined, // Cantor8 doesn't support capability filtering yet\n state,\n redirectUri,\n };\n\n // Create connect URL using vendor module\n const connectUrl = this.vendorModule.createConnectUrl(request, this.vendorConfig);\n\n // Open via transport\n const transportOptions: import('@partylayer/core').TransportOptions = {\n timeoutMs: opts?.timeoutMs || 60000,\n allowedOrigins: [ctx.origin],\n origin: ctx.origin,\n };\n\n const response = await this.transport.openConnectRequest(\n connectUrl,\n request,\n transportOptions\n );\n\n // Check for error\n if (response.error) {\n if (response.error.code === 'USER_REJECTED' || response.error.code === 'CANCELLED') {\n throw new UserRejectedError('User rejected connection');\n }\n throw new Error(response.error.message || 'Connection failed');\n }\n\n if (!response.partyId) {\n throw new Error('No partyId in response');\n }\n\n // Return result\n return {\n partyId: response.partyId,\n session: {\n walletId: this.walletId,\n // Cantor8's connect response carries no network → not wallet-reported,\n // so network-mismatch detection is limited for this adapter (echoes\n // the requested ctx.network).\n network: ctx.network,\n createdAt: Date.now(),\n expiresAt: response.expiresAt,\n capabilitiesSnapshot: (response.capabilities || ['connect', 'signMessage']) as CapabilityKey[],\n metadata: {\n sessionToken: response.sessionToken || '',\n },\n },\n capabilities: (response.capabilities || ['connect', 'signMessage']) as CapabilityKey[],\n };\n } catch (err) {\n throw mapUnknownErrorToPartyLayerError(err, {\n walletId: this.walletId,\n phase: 'connect',\n transport: 'deeplink',\n });\n }\n }\n\n disconnect(\n _ctx: AdapterContext,\n _session: import('@partylayer/core').Session\n ): Promise<void> {\n // Cantor8 doesn't have explicit disconnect - session expires naturally\n // Clear any stored session tokens\n if (_session.metadata?.sessionToken) {\n // In production, might call a logout endpoint\n }\n return Promise.resolve();\n }\n\n restore(\n _ctx: AdapterContext,\n persisted: import('@partylayer/core').PersistedSession\n ): Promise<import('@partylayer/core').Session | null> {\n // Check if we have a session token\n const sessionToken = persisted.metadata?.sessionToken;\n if (typeof sessionToken !== 'string') {\n return Promise.resolve(null); // No token to restore\n }\n\n // In production, might validate token with vendor API\n // For now, if token exists and session not expired, restore\n if (persisted.expiresAt && Date.now() >= persisted.expiresAt) {\n return Promise.resolve(null); // Expired\n }\n\n // Return restored session\n return Promise.resolve({\n ...persisted,\n walletId: this.walletId,\n });\n }\n\n async signMessage(\n ctx: AdapterContext,\n session: import('@partylayer/core').Session,\n params: SignMessageParams\n ): Promise<import('@partylayer/core').SignedMessage> {\n try {\n const state = this.generateState();\n const redirectUri = this.vendorConfig.redirectUri || `${ctx.origin}/callback`;\n const request: import('@partylayer/core').SignRequest = {\n message: params.message,\n state,\n redirectUri,\n };\n\n const signUrl = this.vendorModule.createSignUrl(request, this.vendorConfig);\n\n const transportOptions: import('@partylayer/core').TransportOptions = {\n timeoutMs: 60000,\n allowedOrigins: [ctx.origin],\n origin: ctx.origin,\n };\n\n const response = await this.transport.openSignRequest(\n signUrl,\n request,\n transportOptions\n );\n\n if (response.error) {\n if (response.error.code === 'USER_REJECTED') {\n throw new UserRejectedError('User rejected signing');\n }\n throw new Error(response.error.message || 'Signing failed');\n }\n\n if (!response.signature) {\n throw new Error('No signature in response');\n }\n\n return {\n message: params.message,\n signature: toSignature(response.signature),\n partyId: session.partyId,\n };\n } catch (err) {\n throw mapUnknownErrorToPartyLayerError(err, {\n walletId: this.walletId,\n phase: 'signMessage',\n transport: 'deeplink',\n });\n }\n }\n\n async signTransaction(\n ctx: AdapterContext,\n session: import('@partylayer/core').Session,\n params: SignTransactionParams\n ): Promise<import('@partylayer/core').SignedTransaction> {\n try {\n const state = this.generateState();\n const redirectUri = this.vendorConfig.redirectUri || `${ctx.origin}/callback`;\n const request: import('@partylayer/core').SignRequest = {\n transaction: params.tx,\n state,\n redirectUri,\n };\n\n const signUrl = this.vendorModule.createSignUrl(request, this.vendorConfig);\n\n const transportOptions: import('@partylayer/core').TransportOptions = {\n timeoutMs: 60000,\n allowedOrigins: [ctx.origin],\n origin: ctx.origin,\n };\n\n const response = await this.transport.openSignRequest(\n signUrl,\n request,\n transportOptions\n );\n\n if (response.error) {\n if (response.error.code === 'USER_REJECTED') {\n throw new UserRejectedError('User rejected signing');\n }\n throw new Error(response.error.message || 'Signing failed');\n }\n\n // Handle async approval (jobId)\n if (response.jobId && this.vendorModule.pollJobStatus) {\n const statusUrl = this.vendorConfig.statusEndpoint || '';\n const jobStatus = await this.vendorModule.pollJobStatus(\n response.jobId,\n statusUrl,\n 60000\n );\n\n if (jobStatus.status === 'denied') {\n throw new UserRejectedError('Transaction signing denied');\n }\n\n if (jobStatus.status === 'approved' && jobStatus.result?.signature) {\n const signedTx = typeof params.tx === 'object' && params.tx !== null\n ? { ...params.tx as Record<string, unknown>, signature: jobStatus.result.signature }\n : { tx: params.tx, signature: jobStatus.result.signature };\n return {\n signedTx,\n transactionHash: jobStatus.result.transactionHash\n ? toTransactionHash(jobStatus.result.transactionHash)\n : toTransactionHash('pending'),\n partyId: session.partyId,\n };\n }\n\n throw new Error('Job not completed');\n }\n\n if (!response.signature) {\n throw new Error('No signature in response');\n }\n\n const signedTx = typeof params.tx === 'object' && params.tx !== null\n ? { ...params.tx as Record<string, unknown>, signature: response.signature }\n : { tx: params.tx, signature: response.signature };\n return {\n signedTx,\n transactionHash: response.transactionHash\n ? toTransactionHash(response.transactionHash)\n : toTransactionHash('pending'),\n partyId: session.partyId,\n };\n } catch (err) {\n throw mapUnknownErrorToPartyLayerError(err, {\n walletId: this.walletId,\n phase: 'signTransaction',\n transport: 'deeplink',\n });\n }\n }\n\n /**\n * Generate random state nonce\n */\n private generateState(): string {\n const array = new Uint8Array(32);\n crypto.getRandomValues(array);\n return Array.from(array, (byte) => byte.toString(16).padStart(2, '0')).join('');\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/cantor8-adapter.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * Cantor8 (C8) Wallet Adapter\n *\n * Wraps the wallet's OWN SDK, `@cantor8/wallet-connect-sdk` (`C8WalletProvider`),\n * which opens a popup to the hosted Cantor8 wallet and speaks its own popup +\n * `postMessage` protocol.\n *\n * This is NOT CIP-0103: the SDK exposes no `request({ method })`, no\n * `signMessage`, and no `prepareExecute`, and it discovers itself over a\n * proprietary `c8#provider_discovery` window event rather than\n * `canton:announceProvider`. Until Cantor8 ships an official `ProviderAdapter`\n * (the generic discovery path), a bespoke wrapper on the real SDK is the honest\n * way to integrate it, replacing the previous `cantor8://` deep-link stub.\n *\n * What maps to a real SDK method, and what does not:\n * - `connect` → `C8WalletProvider.connect()` + `getAccounts()` for the party.\n * - `disconnect` → `C8WalletProvider.disconnect()`.\n * - `submitTransaction` → `signAndExecute()` (the SDK fuses sign + execute).\n * - tx status → the SDK's `txChanged` event, surfaced as the `events` capability\n * via `on('txStatus')`.\n * - `signMessage` has NO counterpart in the SDK. It is NOT simulated, NOT routed\n * through a transaction method, and does NOT silently succeed. It fails with\n * `CapabilityNotSupportedError`.\n * - The SDK's networks are `devnet` and `mainnet` only.\n *\n * Reference: `@cantor8/wallet-connect-sdk` (npm, 0.4.0); docs at cantor8.mintlify.app.\n */\n\nimport type {\n WalletAdapter,\n AdapterContext,\n AdapterDetectResult,\n AdapterConnectResult,\n AdapterEventName,\n SignMessageParams,\n SubmitTransactionParams,\n Session,\n SignedMessage,\n TxReceipt,\n} from '@partylayer/core';\nimport {\n toWalletId,\n toPartyId,\n toTransactionHash,\n CapabilityNotSupportedError,\n mapUnknownErrorToPartyLayerError,\n type CapabilityKey,\n} from '@partylayer/core';\n\n// Lazy, SSR-safe access to the wallet's own SDK: the provider touches `window`\n// (it opens a popup), so the import is deferred to first use, mirroring the\n// Console adapter. `@cantor8/wallet-connect-sdk` has zero dependencies.\ntype C8Module = typeof import('@cantor8/wallet-connect-sdk');\ntype C8WalletProviderInstance = InstanceType<C8Module['C8WalletProvider']>;\n\nlet c8ModulePromise: Promise<C8Module> | null = null;\nfunction loadC8(): Promise<C8Module> {\n if (!c8ModulePromise) {\n c8ModulePromise = import('@cantor8/wallet-connect-sdk');\n }\n return c8ModulePromise;\n}\n\n/** The only networks the Cantor8 SDK constructor accepts. */\ntype C8Network = 'devnet' | 'mainnet';\n\n/**\n * The shape `submitTransaction` expects in `params.signedTx`: the Cantor8 SDK's\n * `signAndExecute` input. The caller owns this shape (passthrough).\n */\nexport interface Cantor8SubmitPayload {\n note?: string;\n partyId: string;\n commandId: string;\n commandsJson: string;\n disclosedContracts?: string;\n}\n\n/**\n * Cantor8 adapter configuration.\n */\nexport interface Cantor8AdapterConfig {\n /** dApp URL passed to the Cantor8 SDK popup handshake. Defaults to `ctx.origin`. */\n dappUrl?: string;\n /**\n * How long `detectInstalled()` waits for the wallet's `c8#provider_discovery`\n * announcement before reporting not-detected. Default 300ms.\n */\n detectTimeoutMs?: number;\n}\n\n/**\n * Cantor8 Wallet Adapter.\n */\nexport class Cantor8Adapter implements WalletAdapter {\n readonly walletId = toWalletId('cantor8');\n readonly name = 'Cantor8';\n\n private readonly config: Cantor8AdapterConfig;\n private provider: C8WalletProviderInstance | null = null;\n\n constructor(config: Cantor8AdapterConfig = {}) {\n this.config = config;\n }\n\n getCapabilities(): CapabilityKey[] {\n // No 'signMessage' (the SDK has none) and no 'signTransaction' (the SDK only\n // fuses sign + execute via signAndExecute). Tx status is delivered as events.\n return ['connect', 'disconnect', 'submitTransaction', 'events', 'popup'];\n }\n\n /** The SDK supports devnet and mainnet only; anything else fails at connect. */\n private mapNetwork(network: string): C8Network {\n if (network === 'devnet') return 'devnet';\n if (network === 'mainnet') return 'mainnet';\n throw new Error(\n `Cantor8 does not support the \"${network}\" network (supported: devnet, mainnet).`,\n );\n }\n\n async detectInstalled(): Promise<AdapterDetectResult> {\n if (typeof window === 'undefined') {\n return { installed: false, reason: 'Browser environment required' };\n }\n // Use Cantor8's OWN discovery event, not a user-agent sniff. The old sniff\n // mislabeled this desktop popup wallet as mobile; `onC8ProviderDiscovered`\n // resolves when a C8 provider announces over `c8#provider_discovery`.\n const { onC8ProviderDiscovered } = await loadC8();\n const timeoutMs = this.config.detectTimeoutMs ?? 300;\n return new Promise<AdapterDetectResult>((resolve) => {\n let settled = false;\n const state: { unsubscribe?: () => void } = {};\n const finish = (result: AdapterDetectResult) => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n try {\n state.unsubscribe?.();\n } catch {\n /* ignore */\n }\n resolve(result);\n };\n const timer = setTimeout(\n () =>\n finish({\n installed: false,\n reason: 'Cantor8 wallet did not announce (no c8#provider_discovery event)',\n }),\n timeoutMs,\n );\n state.unsubscribe = onC8ProviderDiscovered(() => finish({ installed: true }));\n });\n }\n\n async connect(\n ctx: AdapterContext,\n _opts?: { timeoutMs?: number },\n ): Promise<AdapterConnectResult> {\n try {\n const { C8WalletProvider } = await loadC8();\n const provider = new C8WalletProvider({\n dappName: ctx.appName,\n dappUrl: this.config.dappUrl ?? ctx.origin,\n network: this.mapNetwork(ctx.network),\n });\n // Cantor8's connect() resolves void; the party is read from getAccounts().\n await provider.connect();\n const { accounts } = await provider.getAccounts();\n const partyId = accounts?.[0]?.partyId;\n if (!partyId) {\n throw new Error('Cantor8 returned no account after connect');\n }\n this.provider = provider;\n return {\n partyId: toPartyId(partyId),\n session: {\n walletId: this.walletId,\n // Cantor8's connect carries no network → echo the requested one.\n network: ctx.network,\n createdAt: Date.now(),\n },\n capabilities: this.getCapabilities(),\n };\n } catch (err) {\n throw mapUnknownErrorToPartyLayerError(err, {\n walletId: this.walletId,\n phase: 'connect',\n transport: 'popup',\n });\n }\n }\n\n async disconnect(_ctx: AdapterContext, _session: Session): Promise<void> {\n if (!this.provider) return;\n try {\n await this.provider.disconnect();\n } finally {\n this.provider = null;\n }\n }\n\n /**\n * Cantor8 has NO arbitrary-message signing. Per the honesty rule: do not\n * simulate it, do not route it through `signAndExecute` (which is for\n * transactions), and do not silently succeed. Fail with the typed capability\n * error. `signMessage` is also absent from `getCapabilities()`, so the SDK's\n * capability guard blocks it first; this is the belt-and-suspenders backstop.\n */\n signMessage(\n _ctx: AdapterContext,\n _session: Session,\n _params: SignMessageParams,\n ): Promise<SignedMessage> {\n return Promise.reject(\n new CapabilityNotSupportedError(String(this.walletId), 'signMessage'),\n );\n }\n\n /**\n * Submit a transaction through the SDK's `signAndExecute` (sign + execute\n * fused; the wallet has no separate sign step). `params.signedTx` is passed\n * through: the caller owns its shape, which must be a {@link Cantor8SubmitPayload}.\n *\n * The SDK's `signAndExecute` resolves with no id; Cantor8 delivers the\n * on-ledger txId and status asynchronously via the `txChanged` event (surfaced\n * through `on('txStatus')`). The receipt is therefore keyed on the\n * caller-supplied `commandId`; the confirmed ledger id arrives on the event\n * stream. A live run against the real wallet is required to confirm\n * end-to-end execution.\n */\n async submitTransaction(\n _ctx: AdapterContext,\n _session: Session,\n params: SubmitTransactionParams,\n ): Promise<TxReceipt> {\n try {\n if (!this.provider) {\n throw new Error('Not connected to Cantor8');\n }\n const input = params.signedTx as Cantor8SubmitPayload;\n if (\n !input ||\n typeof input.commandId !== 'string' ||\n typeof input.commandsJson !== 'string' ||\n typeof input.partyId !== 'string'\n ) {\n throw new Error(\n 'Cantor8 submitTransaction requires signedTx to be the SDK signAndExecute '\n + 'input { note?, partyId, commandId, commandsJson, disclosedContracts? }.',\n );\n }\n await this.provider.signAndExecute({\n note: input.note ?? '',\n partyId: input.partyId,\n commandId: input.commandId,\n commandsJson: input.commandsJson,\n disclosedContracts: input.disclosedContracts ?? '',\n });\n // signAndExecute returns no id; key the receipt on the caller's commandId.\n // The confirmed ledger txId + status arrive via the txChanged event.\n return {\n transactionHash: toTransactionHash(input.commandId),\n submittedAt: Date.now(),\n commandId: input.commandId,\n };\n } catch (err) {\n throw mapUnknownErrorToPartyLayerError(err, {\n walletId: this.walletId,\n phase: 'submitTransaction',\n transport: 'popup',\n });\n }\n }\n\n /**\n * Forward the wallet's transaction-status stream. Cantor8 emits `txChanged`\n * ({ txId, status }); PartyLayer surfaces this as the `events` capability under\n * the `txStatus` event. Any other event name is a no-op. Returns an\n * unsubscribe function.\n */\n on(event: AdapterEventName, handler: (payload: unknown) => void): () => void {\n if (event !== 'txStatus' || !this.provider) {\n return () => {\n /* nothing subscribed */\n };\n }\n const off = this.provider.on('txChanged', (e) => {\n handler({ txId: e.txId, status: e.status });\n });\n return () => {\n try {\n off();\n } catch {\n /* ignore */\n }\n };\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@partylayer/adapter-cantor8",
3
- "version": "0.2.20",
3
+ "version": "0.3.0",
4
4
  "sideEffects": false,
5
5
  "description": "Cantor8 (C8) Wallet adapter for PartyLayer",
6
6
  "main": "./dist/index.js",
@@ -33,6 +33,7 @@
33
33
  "url": "https://github.com/PartyLayer/PartyLayer/issues"
34
34
  },
35
35
  "dependencies": {
36
+ "@cantor8/wallet-connect-sdk": "^0.4.0",
36
37
  "@partylayer/core": "^0.12.1"
37
38
  },
38
39
  "devDependencies": {