@partylayer/adapter-cantor8 0.3.0 → 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/index.d.mts CHANGED
@@ -18,11 +18,6 @@ interface Cantor8SubmitPayload {
18
18
  interface Cantor8AdapterConfig {
19
19
  /** dApp URL passed to the Cantor8 SDK popup handshake. Defaults to `ctx.origin`. */
20
20
  dappUrl?: string;
21
- /**
22
- * How long `detectInstalled()` waits for the wallet's `c8#provider_discovery`
23
- * announcement before reporting not-detected. Default 300ms.
24
- */
25
- detectTimeoutMs?: number;
26
21
  }
27
22
  /**
28
23
  * Cantor8 Wallet Adapter.
@@ -36,6 +31,45 @@ declare class Cantor8Adapter implements WalletAdapter {
36
31
  getCapabilities(): CapabilityKey[];
37
32
  /** The SDK supports devnet and mainnet only; anything else fails at connect. */
38
33
  private mapNetwork;
34
+ /**
35
+ * Cantor8 is a HOSTED POPUP wallet: connect() opens the wallet at
36
+ * wallet.dev.digik.cantor8.tech (devnet) or wallet.cantor8.tech (mainnet)
37
+ * through the SDK's C8WalletProvider. Nothing of Cantor8 runs in THIS page, so
38
+ * there is nothing here to detect.
39
+ *
40
+ * The SDK's discovery protocol has two sides. `announceC8Provider(get)` is the
41
+ * DISPATCH side, called by a wallet that lives in the page to advertise a
42
+ * provider factory; `onC8ProviderDiscovered(cb)` is the SUBSCRIBE side, called
43
+ * by a dApp to hear such an announcement. A hosted popup on another origin never
44
+ * calls `announceC8Provider` in our page, so subscribing and waiting for the
45
+ * `c8#provider_discovery` event can only ever time out. That is precisely what
46
+ * the previous strategy did, and it reported Cantor8 permanently unavailable,
47
+ * which hid it from the picker.
48
+ *
49
+ * The right model is the gateway contract the official ProviderAdapter path uses
50
+ * (see GenericDiscoveryAdapter.detectInstalled): a gateway is reachable wherever
51
+ * it can be opened, so detect reports available and the REAL availability check
52
+ * happens at connect(), when the popup opens. Walley, a popup wallet on that
53
+ * generic path, works in our demos for exactly this reason.
54
+ *
55
+ * This is the SECOND detection strategy to be wrong here, both from the same
56
+ * root cause: inferring the wallet's shape without the wallet in hand. First a
57
+ * user-agent sniff mislabeled this desktop popup as a mobile wallet; then the
58
+ * announcement wait assumed an in-page announcer that a hosted popup never
59
+ * provides. Do not reintroduce a probe that depends on something being in the
60
+ * page. If a future in-page Cantor8 ever announces over `c8#provider_discovery`,
61
+ * it may be adopted as a fast path, but it must NEVER be the condition for
62
+ * availability.
63
+ *
64
+ * detect still LOADS the SDK (the pre-fix detect did too; only its announcement
65
+ * wait was wrong). This is deliberate warming, not detection: a bespoke adapter
66
+ * does not get the SDK's popup-safe fast-path (that is for GenericDiscoveryAdapter),
67
+ * so connect() reaches window.open only after awaits. detect runs at picker
68
+ * render, off the click gesture, so the dynamic import resolves before the user
69
+ * clicks; connect()'s `await loadC8()` is then a resolved microtask instead of a
70
+ * cold import that would defer window.open past the gesture and let the browser
71
+ * block the popup.
72
+ */
39
73
  detectInstalled(): Promise<AdapterDetectResult>;
40
74
  connect(ctx: AdapterContext, _opts?: {
41
75
  timeoutMs?: number;
package/dist/index.d.ts CHANGED
@@ -18,11 +18,6 @@ interface Cantor8SubmitPayload {
18
18
  interface Cantor8AdapterConfig {
19
19
  /** dApp URL passed to the Cantor8 SDK popup handshake. Defaults to `ctx.origin`. */
20
20
  dappUrl?: string;
21
- /**
22
- * How long `detectInstalled()` waits for the wallet's `c8#provider_discovery`
23
- * announcement before reporting not-detected. Default 300ms.
24
- */
25
- detectTimeoutMs?: number;
26
21
  }
27
22
  /**
28
23
  * Cantor8 Wallet Adapter.
@@ -36,6 +31,45 @@ declare class Cantor8Adapter implements WalletAdapter {
36
31
  getCapabilities(): CapabilityKey[];
37
32
  /** The SDK supports devnet and mainnet only; anything else fails at connect. */
38
33
  private mapNetwork;
34
+ /**
35
+ * Cantor8 is a HOSTED POPUP wallet: connect() opens the wallet at
36
+ * wallet.dev.digik.cantor8.tech (devnet) or wallet.cantor8.tech (mainnet)
37
+ * through the SDK's C8WalletProvider. Nothing of Cantor8 runs in THIS page, so
38
+ * there is nothing here to detect.
39
+ *
40
+ * The SDK's discovery protocol has two sides. `announceC8Provider(get)` is the
41
+ * DISPATCH side, called by a wallet that lives in the page to advertise a
42
+ * provider factory; `onC8ProviderDiscovered(cb)` is the SUBSCRIBE side, called
43
+ * by a dApp to hear such an announcement. A hosted popup on another origin never
44
+ * calls `announceC8Provider` in our page, so subscribing and waiting for the
45
+ * `c8#provider_discovery` event can only ever time out. That is precisely what
46
+ * the previous strategy did, and it reported Cantor8 permanently unavailable,
47
+ * which hid it from the picker.
48
+ *
49
+ * The right model is the gateway contract the official ProviderAdapter path uses
50
+ * (see GenericDiscoveryAdapter.detectInstalled): a gateway is reachable wherever
51
+ * it can be opened, so detect reports available and the REAL availability check
52
+ * happens at connect(), when the popup opens. Walley, a popup wallet on that
53
+ * generic path, works in our demos for exactly this reason.
54
+ *
55
+ * This is the SECOND detection strategy to be wrong here, both from the same
56
+ * root cause: inferring the wallet's shape without the wallet in hand. First a
57
+ * user-agent sniff mislabeled this desktop popup as a mobile wallet; then the
58
+ * announcement wait assumed an in-page announcer that a hosted popup never
59
+ * provides. Do not reintroduce a probe that depends on something being in the
60
+ * page. If a future in-page Cantor8 ever announces over `c8#provider_discovery`,
61
+ * it may be adopted as a fast path, but it must NEVER be the condition for
62
+ * availability.
63
+ *
64
+ * detect still LOADS the SDK (the pre-fix detect did too; only its announcement
65
+ * wait was wrong). This is deliberate warming, not detection: a bespoke adapter
66
+ * does not get the SDK's popup-safe fast-path (that is for GenericDiscoveryAdapter),
67
+ * so connect() reaches window.open only after awaits. detect runs at picker
68
+ * render, off the click gesture, so the dynamic import resolves before the user
69
+ * clicks; connect()'s `await loadC8()` is then a resolved microtask instead of a
70
+ * cold import that would defer window.open past the gesture and let the browser
71
+ * block the popup.
72
+ */
39
73
  detectInstalled(): Promise<AdapterDetectResult>;
40
74
  connect(ctx: AdapterContext, _opts?: {
41
75
  timeoutMs?: number;
package/dist/index.js CHANGED
@@ -29,34 +29,54 @@ var Cantor8Adapter = class {
29
29
  `Cantor8 does not support the "${network}" network (supported: devnet, mainnet).`
30
30
  );
31
31
  }
32
+ /**
33
+ * Cantor8 is a HOSTED POPUP wallet: connect() opens the wallet at
34
+ * wallet.dev.digik.cantor8.tech (devnet) or wallet.cantor8.tech (mainnet)
35
+ * through the SDK's C8WalletProvider. Nothing of Cantor8 runs in THIS page, so
36
+ * there is nothing here to detect.
37
+ *
38
+ * The SDK's discovery protocol has two sides. `announceC8Provider(get)` is the
39
+ * DISPATCH side, called by a wallet that lives in the page to advertise a
40
+ * provider factory; `onC8ProviderDiscovered(cb)` is the SUBSCRIBE side, called
41
+ * by a dApp to hear such an announcement. A hosted popup on another origin never
42
+ * calls `announceC8Provider` in our page, so subscribing and waiting for the
43
+ * `c8#provider_discovery` event can only ever time out. That is precisely what
44
+ * the previous strategy did, and it reported Cantor8 permanently unavailable,
45
+ * which hid it from the picker.
46
+ *
47
+ * The right model is the gateway contract the official ProviderAdapter path uses
48
+ * (see GenericDiscoveryAdapter.detectInstalled): a gateway is reachable wherever
49
+ * it can be opened, so detect reports available and the REAL availability check
50
+ * happens at connect(), when the popup opens. Walley, a popup wallet on that
51
+ * generic path, works in our demos for exactly this reason.
52
+ *
53
+ * This is the SECOND detection strategy to be wrong here, both from the same
54
+ * root cause: inferring the wallet's shape without the wallet in hand. First a
55
+ * user-agent sniff mislabeled this desktop popup as a mobile wallet; then the
56
+ * announcement wait assumed an in-page announcer that a hosted popup never
57
+ * provides. Do not reintroduce a probe that depends on something being in the
58
+ * page. If a future in-page Cantor8 ever announces over `c8#provider_discovery`,
59
+ * it may be adopted as a fast path, but it must NEVER be the condition for
60
+ * availability.
61
+ *
62
+ * detect still LOADS the SDK (the pre-fix detect did too; only its announcement
63
+ * wait was wrong). This is deliberate warming, not detection: a bespoke adapter
64
+ * does not get the SDK's popup-safe fast-path (that is for GenericDiscoveryAdapter),
65
+ * so connect() reaches window.open only after awaits. detect runs at picker
66
+ * render, off the click gesture, so the dynamic import resolves before the user
67
+ * clicks; connect()'s `await loadC8()` is then a resolved microtask instead of a
68
+ * cold import that would defer window.open past the gesture and let the browser
69
+ * block the popup.
70
+ */
32
71
  async detectInstalled() {
33
72
  if (typeof window === "undefined") {
34
73
  return { installed: false, reason: "Browser environment required" };
35
74
  }
36
- const { onC8ProviderDiscovered } = await loadC8();
37
- const timeoutMs = this.config.detectTimeoutMs ?? 300;
38
- return new Promise((resolve) => {
39
- let settled = false;
40
- const state = {};
41
- const finish = (result) => {
42
- if (settled) return;
43
- settled = true;
44
- clearTimeout(timer);
45
- try {
46
- state.unsubscribe?.();
47
- } catch {
48
- }
49
- resolve(result);
50
- };
51
- const timer = setTimeout(
52
- () => finish({
53
- installed: false,
54
- reason: "Cantor8 wallet did not announce (no c8#provider_discovery event)"
55
- }),
56
- timeoutMs
57
- );
58
- state.unsubscribe = onC8ProviderDiscovered(() => finish({ installed: true }));
59
- });
75
+ try {
76
+ await loadC8();
77
+ } catch {
78
+ }
79
+ return { installed: true };
60
80
  }
61
81
  async connect(ctx, _opts) {
62
82
  try {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cantor8-adapter.ts"],"names":["toWalletId","toPartyId","mapUnknownErrorToPartyLayerError","CapabilityNotSupportedError","toTransactionHash"],"mappings":";;;;;AAuDA,IAAI,eAAA,GAA4C,IAAA;AAChD,SAAS,MAAA,GAA4B;AACnC,EAAA,IAAI,CAAC,eAAA,EAAiB;AACpB,IAAA,eAAA,GAAkB,OAAO,6BAA6B,CAAA;AAAA,EACxD;AACA,EAAA,OAAO,eAAA;AACT;AAiCO,IAAM,iBAAN,MAA8C;AAAA,EAC1C,QAAA,GAAWA,gBAAW,SAAS,CAAA;AAAA,EAC/B,IAAA,GAAO,SAAA;AAAA,EAEC,MAAA;AAAA,EACT,QAAA,GAA4C,IAAA;AAAA,EAEpD,WAAA,CAAY,MAAA,GAA+B,EAAC,EAAG;AAC7C,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AAAA,EAChB;AAAA,EAEA,eAAA,GAAmC;AAGjC,IAAA,OAAO,CAAC,SAAA,EAAW,YAAA,EAAc,mBAAA,EAAqB,UAAU,OAAO,CAAA;AAAA,EACzE;AAAA;AAAA,EAGQ,WAAW,OAAA,EAA4B;AAC7C,IAAA,IAAI,OAAA,KAAY,UAAU,OAAO,QAAA;AACjC,IAAA,IAAI,OAAA,KAAY,WAAW,OAAO,SAAA;AAClC,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,iCAAiC,OAAO,CAAA,uCAAA;AAAA,KAC1C;AAAA,EACF;AAAA,EAEA,MAAM,eAAA,GAAgD;AACpD,IAAA,IAAI,OAAO,WAAW,WAAA,EAAa;AACjC,MAAA,OAAO,EAAE,SAAA,EAAW,KAAA,EAAO,MAAA,EAAQ,8BAAA,EAA+B;AAAA,IACpE;AAIA,IAAA,MAAM,EAAE,sBAAA,EAAuB,GAAI,MAAM,MAAA,EAAO;AAChD,IAAA,MAAM,SAAA,GAAY,IAAA,CAAK,MAAA,CAAO,eAAA,IAAmB,GAAA;AACjD,IAAA,OAAO,IAAI,OAAA,CAA6B,CAAC,OAAA,KAAY;AACnD,MAAA,IAAI,OAAA,GAAU,KAAA;AACd,MAAA,MAAM,QAAsC,EAAC;AAC7C,MAAA,MAAM,MAAA,GAAS,CAAC,MAAA,KAAgC;AAC9C,QAAA,IAAI,OAAA,EAAS;AACb,QAAA,OAAA,GAAU,IAAA;AACV,QAAA,YAAA,CAAa,KAAK,CAAA;AAClB,QAAA,IAAI;AACF,UAAA,KAAA,CAAM,WAAA,IAAc;AAAA,QACtB,CAAA,CAAA,MAAQ;AAAA,QAER;AACA,QAAA,OAAA,CAAQ,MAAM,CAAA;AAAA,MAChB,CAAA;AACA,MAAA,MAAM,KAAA,GAAQ,UAAA;AAAA,QACZ,MACE,MAAA,CAAO;AAAA,UACL,SAAA,EAAW,KAAA;AAAA,UACX,MAAA,EAAQ;AAAA,SACT,CAAA;AAAA,QACH;AAAA,OACF;AACA,MAAA,KAAA,CAAM,WAAA,GAAc,uBAAuB,MAAM,MAAA,CAAO,EAAE,SAAA,EAAW,IAAA,EAAM,CAAC,CAAA;AAAA,IAC9E,CAAC,CAAA;AAAA,EACH;AAAA,EAEA,MAAM,OAAA,CACJ,GAAA,EACA,KAAA,EAC+B;AAC/B,IAAA,IAAI;AACF,MAAA,MAAM,EAAE,gBAAA,EAAiB,GAAI,MAAM,MAAA,EAAO;AAC1C,MAAA,MAAM,QAAA,GAAW,IAAI,gBAAA,CAAiB;AAAA,QACpC,UAAU,GAAA,CAAI,OAAA;AAAA,QACd,OAAA,EAAS,IAAA,CAAK,MAAA,CAAO,OAAA,IAAW,GAAA,CAAI,MAAA;AAAA,QACpC,OAAA,EAAS,IAAA,CAAK,UAAA,CAAW,GAAA,CAAI,OAAO;AAAA,OACrC,CAAA;AAED,MAAA,MAAM,SAAS,OAAA,EAAQ;AACvB,MAAA,MAAM,EAAE,QAAA,EAAS,GAAI,MAAM,SAAS,WAAA,EAAY;AAChD,MAAA,MAAM,OAAA,GAAU,QAAA,GAAW,CAAC,CAAA,EAAG,OAAA;AAC/B,MAAA,IAAI,CAAC,OAAA,EAAS;AACZ,QAAA,MAAM,IAAI,MAAM,2CAA2C,CAAA;AAAA,MAC7D;AACA,MAAA,IAAA,CAAK,QAAA,GAAW,QAAA;AAChB,MAAA,OAAO;AAAA,QACL,OAAA,EAASC,eAAU,OAAO,CAAA;AAAA,QAC1B,OAAA,EAAS;AAAA,UACP,UAAU,IAAA,CAAK,QAAA;AAAA;AAAA,UAEf,SAAS,GAAA,CAAI,OAAA;AAAA,UACb,SAAA,EAAW,KAAK,GAAA;AAAI,SACtB;AAAA,QACA,YAAA,EAAc,KAAK,eAAA;AAAgB,OACrC;AAAA,IACF,SAAS,GAAA,EAAK;AACZ,MAAA,MAAMC,sCAAiC,GAAA,EAAK;AAAA,QAC1C,UAAU,IAAA,CAAK,QAAA;AAAA,QACf,KAAA,EAAO,SAAA;AAAA,QACP,SAAA,EAAW;AAAA,OACZ,CAAA;AAAA,IACH;AAAA,EACF;AAAA,EAEA,MAAM,UAAA,CAAW,IAAA,EAAsB,QAAA,EAAkC;AACvE,IAAA,IAAI,CAAC,KAAK,QAAA,EAAU;AACpB,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,CAAK,SAAS,UAAA,EAAW;AAAA,IACjC,CAAA,SAAE;AACA,MAAA,IAAA,CAAK,QAAA,GAAW,IAAA;AAAA,IAClB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,WAAA,CACE,IAAA,EACA,QAAA,EACA,OAAA,EACwB;AACxB,IAAA,OAAO,OAAA,CAAQ,MAAA;AAAA,MACb,IAAIC,gCAAA,CAA4B,MAAA,CAAO,IAAA,CAAK,QAAQ,GAAG,aAAa;AAAA,KACtE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAM,iBAAA,CACJ,IAAA,EACA,QAAA,EACA,MAAA,EACoB;AACpB,IAAA,IAAI;AACF,MAAA,IAAI,CAAC,KAAK,QAAA,EAAU;AAClB,QAAA,MAAM,IAAI,MAAM,0BAA0B,CAAA;AAAA,MAC5C;AACA,MAAA,MAAM,QAAQ,MAAA,CAAO,QAAA;AACrB,MAAA,IACE,CAAC,KAAA,IACD,OAAO,KAAA,CAAM,SAAA,KAAc,QAAA,IAC3B,OAAO,KAAA,CAAM,YAAA,KAAiB,QAAA,IAC9B,OAAO,KAAA,CAAM,YAAY,QAAA,EACzB;AACA,QAAA,MAAM,IAAI,KAAA;AAAA,UACR;AAAA,SAEF;AAAA,MACF;AACA,MAAA,MAAM,IAAA,CAAK,SAAS,cAAA,CAAe;AAAA,QACjC,IAAA,EAAM,MAAM,IAAA,IAAQ,EAAA;AAAA,QACpB,SAAS,KAAA,CAAM,OAAA;AAAA,QACf,WAAW,KAAA,CAAM,SAAA;AAAA,QACjB,cAAc,KAAA,CAAM,YAAA;AAAA,QACpB,kBAAA,EAAoB,MAAM,kBAAA,IAAsB;AAAA,OACjD,CAAA;AAGD,MAAA,OAAO;AAAA,QACL,eAAA,EAAiBC,sBAAA,CAAkB,KAAA,CAAM,SAAS,CAAA;AAAA,QAClD,WAAA,EAAa,KAAK,GAAA,EAAI;AAAA,QACtB,WAAW,KAAA,CAAM;AAAA,OACnB;AAAA,IACF,SAAS,GAAA,EAAK;AACZ,MAAA,MAAMF,sCAAiC,GAAA,EAAK;AAAA,QAC1C,UAAU,IAAA,CAAK,QAAA;AAAA,QACf,KAAA,EAAO,mBAAA;AAAA,QACP,SAAA,EAAW;AAAA,OACZ,CAAA;AAAA,IACH;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,EAAA,CAAG,OAAyB,OAAA,EAAiD;AAC3E,IAAA,IAAI,KAAA,KAAU,UAAA,IAAc,CAAC,IAAA,CAAK,QAAA,EAAU;AAC1C,MAAA,OAAO,MAAM;AAAA,MAEb,CAAA;AAAA,IACF;AACA,IAAA,MAAM,MAAM,IAAA,CAAK,QAAA,CAAS,EAAA,CAAG,WAAA,EAAa,CAAC,CAAA,KAAM;AAC/C,MAAA,OAAA,CAAQ,EAAE,IAAA,EAAM,CAAA,CAAE,MAAM,MAAA,EAAQ,CAAA,CAAE,QAAQ,CAAA;AAAA,IAC5C,CAAC,CAAA;AACD,IAAA,OAAO,MAAM;AACX,MAAA,IAAI;AACF,QAAA,GAAA,EAAI;AAAA,MACN,CAAA,CAAA,MAAQ;AAAA,MAER;AAAA,IACF,CAAA;AAAA,EACF;AACF","file":"index.js","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"]}
1
+ {"version":3,"sources":["../src/cantor8-adapter.ts"],"names":["toWalletId","toPartyId","mapUnknownErrorToPartyLayerError","CapabilityNotSupportedError","toTransactionHash"],"mappings":"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","file":"index.js","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\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 /**\n * Cantor8 is a HOSTED POPUP wallet: connect() opens the wallet at\n * wallet.dev.digik.cantor8.tech (devnet) or wallet.cantor8.tech (mainnet)\n * through the SDK's C8WalletProvider. Nothing of Cantor8 runs in THIS page, so\n * there is nothing here to detect.\n *\n * The SDK's discovery protocol has two sides. `announceC8Provider(get)` is the\n * DISPATCH side, called by a wallet that lives in the page to advertise a\n * provider factory; `onC8ProviderDiscovered(cb)` is the SUBSCRIBE side, called\n * by a dApp to hear such an announcement. A hosted popup on another origin never\n * calls `announceC8Provider` in our page, so subscribing and waiting for the\n * `c8#provider_discovery` event can only ever time out. That is precisely what\n * the previous strategy did, and it reported Cantor8 permanently unavailable,\n * which hid it from the picker.\n *\n * The right model is the gateway contract the official ProviderAdapter path uses\n * (see GenericDiscoveryAdapter.detectInstalled): a gateway is reachable wherever\n * it can be opened, so detect reports available and the REAL availability check\n * happens at connect(), when the popup opens. Walley, a popup wallet on that\n * generic path, works in our demos for exactly this reason.\n *\n * This is the SECOND detection strategy to be wrong here, both from the same\n * root cause: inferring the wallet's shape without the wallet in hand. First a\n * user-agent sniff mislabeled this desktop popup as a mobile wallet; then the\n * announcement wait assumed an in-page announcer that a hosted popup never\n * provides. Do not reintroduce a probe that depends on something being in the\n * page. If a future in-page Cantor8 ever announces over `c8#provider_discovery`,\n * it may be adopted as a fast path, but it must NEVER be the condition for\n * availability.\n *\n * detect still LOADS the SDK (the pre-fix detect did too; only its announcement\n * wait was wrong). This is deliberate warming, not detection: a bespoke adapter\n * does not get the SDK's popup-safe fast-path (that is for GenericDiscoveryAdapter),\n * so connect() reaches window.open only after awaits. detect runs at picker\n * render, off the click gesture, so the dynamic import resolves before the user\n * clicks; connect()'s `await loadC8()` is then a resolved microtask instead of a\n * cold import that would defer window.open past the gesture and let the browser\n * block the popup.\n */\n async detectInstalled(): Promise<AdapterDetectResult> {\n if (typeof window === 'undefined') {\n return { installed: false, reason: 'Browser environment required' };\n }\n // Warm the SDK module (see the warming note above). A load failure is not\n // fatal to availability; it surfaces at connect() where the real work happens.\n try {\n await loadC8();\n } catch {\n /* ignore; connect() surfaces a genuine SDK load failure */\n }\n return { installed: true };\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/dist/index.mjs CHANGED
@@ -27,34 +27,54 @@ var Cantor8Adapter = class {
27
27
  `Cantor8 does not support the "${network}" network (supported: devnet, mainnet).`
28
28
  );
29
29
  }
30
+ /**
31
+ * Cantor8 is a HOSTED POPUP wallet: connect() opens the wallet at
32
+ * wallet.dev.digik.cantor8.tech (devnet) or wallet.cantor8.tech (mainnet)
33
+ * through the SDK's C8WalletProvider. Nothing of Cantor8 runs in THIS page, so
34
+ * there is nothing here to detect.
35
+ *
36
+ * The SDK's discovery protocol has two sides. `announceC8Provider(get)` is the
37
+ * DISPATCH side, called by a wallet that lives in the page to advertise a
38
+ * provider factory; `onC8ProviderDiscovered(cb)` is the SUBSCRIBE side, called
39
+ * by a dApp to hear such an announcement. A hosted popup on another origin never
40
+ * calls `announceC8Provider` in our page, so subscribing and waiting for the
41
+ * `c8#provider_discovery` event can only ever time out. That is precisely what
42
+ * the previous strategy did, and it reported Cantor8 permanently unavailable,
43
+ * which hid it from the picker.
44
+ *
45
+ * The right model is the gateway contract the official ProviderAdapter path uses
46
+ * (see GenericDiscoveryAdapter.detectInstalled): a gateway is reachable wherever
47
+ * it can be opened, so detect reports available and the REAL availability check
48
+ * happens at connect(), when the popup opens. Walley, a popup wallet on that
49
+ * generic path, works in our demos for exactly this reason.
50
+ *
51
+ * This is the SECOND detection strategy to be wrong here, both from the same
52
+ * root cause: inferring the wallet's shape without the wallet in hand. First a
53
+ * user-agent sniff mislabeled this desktop popup as a mobile wallet; then the
54
+ * announcement wait assumed an in-page announcer that a hosted popup never
55
+ * provides. Do not reintroduce a probe that depends on something being in the
56
+ * page. If a future in-page Cantor8 ever announces over `c8#provider_discovery`,
57
+ * it may be adopted as a fast path, but it must NEVER be the condition for
58
+ * availability.
59
+ *
60
+ * detect still LOADS the SDK (the pre-fix detect did too; only its announcement
61
+ * wait was wrong). This is deliberate warming, not detection: a bespoke adapter
62
+ * does not get the SDK's popup-safe fast-path (that is for GenericDiscoveryAdapter),
63
+ * so connect() reaches window.open only after awaits. detect runs at picker
64
+ * render, off the click gesture, so the dynamic import resolves before the user
65
+ * clicks; connect()'s `await loadC8()` is then a resolved microtask instead of a
66
+ * cold import that would defer window.open past the gesture and let the browser
67
+ * block the popup.
68
+ */
30
69
  async detectInstalled() {
31
70
  if (typeof window === "undefined") {
32
71
  return { installed: false, reason: "Browser environment required" };
33
72
  }
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 }));
57
- });
73
+ try {
74
+ await loadC8();
75
+ } catch {
76
+ }
77
+ return { installed: true };
58
78
  }
59
79
  async connect(ctx, _opts) {
60
80
  try {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cantor8-adapter.ts"],"names":[],"mappings":";;;AAuDA,IAAI,eAAA,GAA4C,IAAA;AAChD,SAAS,MAAA,GAA4B;AACnC,EAAA,IAAI,CAAC,eAAA,EAAiB;AACpB,IAAA,eAAA,GAAkB,OAAO,6BAA6B,CAAA;AAAA,EACxD;AACA,EAAA,OAAO,eAAA;AACT;AAiCO,IAAM,iBAAN,MAA8C;AAAA,EAC1C,QAAA,GAAW,WAAW,SAAS,CAAA;AAAA,EAC/B,IAAA,GAAO,SAAA;AAAA,EAEC,MAAA;AAAA,EACT,QAAA,GAA4C,IAAA;AAAA,EAEpD,WAAA,CAAY,MAAA,GAA+B,EAAC,EAAG;AAC7C,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AAAA,EAChB;AAAA,EAEA,eAAA,GAAmC;AAGjC,IAAA,OAAO,CAAC,SAAA,EAAW,YAAA,EAAc,mBAAA,EAAqB,UAAU,OAAO,CAAA;AAAA,EACzE;AAAA;AAAA,EAGQ,WAAW,OAAA,EAA4B;AAC7C,IAAA,IAAI,OAAA,KAAY,UAAU,OAAO,QAAA;AACjC,IAAA,IAAI,OAAA,KAAY,WAAW,OAAO,SAAA;AAClC,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,iCAAiC,OAAO,CAAA,uCAAA;AAAA,KAC1C;AAAA,EACF;AAAA,EAEA,MAAM,eAAA,GAAgD;AACpD,IAAA,IAAI,OAAO,WAAW,WAAA,EAAa;AACjC,MAAA,OAAO,EAAE,SAAA,EAAW,KAAA,EAAO,MAAA,EAAQ,8BAAA,EAA+B;AAAA,IACpE;AAIA,IAAA,MAAM,EAAE,sBAAA,EAAuB,GAAI,MAAM,MAAA,EAAO;AAChD,IAAA,MAAM,SAAA,GAAY,IAAA,CAAK,MAAA,CAAO,eAAA,IAAmB,GAAA;AACjD,IAAA,OAAO,IAAI,OAAA,CAA6B,CAAC,OAAA,KAAY;AACnD,MAAA,IAAI,OAAA,GAAU,KAAA;AACd,MAAA,MAAM,QAAsC,EAAC;AAC7C,MAAA,MAAM,MAAA,GAAS,CAAC,MAAA,KAAgC;AAC9C,QAAA,IAAI,OAAA,EAAS;AACb,QAAA,OAAA,GAAU,IAAA;AACV,QAAA,YAAA,CAAa,KAAK,CAAA;AAClB,QAAA,IAAI;AACF,UAAA,KAAA,CAAM,WAAA,IAAc;AAAA,QACtB,CAAA,CAAA,MAAQ;AAAA,QAER;AACA,QAAA,OAAA,CAAQ,MAAM,CAAA;AAAA,MAChB,CAAA;AACA,MAAA,MAAM,KAAA,GAAQ,UAAA;AAAA,QACZ,MACE,MAAA,CAAO;AAAA,UACL,SAAA,EAAW,KAAA;AAAA,UACX,MAAA,EAAQ;AAAA,SACT,CAAA;AAAA,QACH;AAAA,OACF;AACA,MAAA,KAAA,CAAM,WAAA,GAAc,uBAAuB,MAAM,MAAA,CAAO,EAAE,SAAA,EAAW,IAAA,EAAM,CAAC,CAAA;AAAA,IAC9E,CAAC,CAAA;AAAA,EACH;AAAA,EAEA,MAAM,OAAA,CACJ,GAAA,EACA,KAAA,EAC+B;AAC/B,IAAA,IAAI;AACF,MAAA,MAAM,EAAE,gBAAA,EAAiB,GAAI,MAAM,MAAA,EAAO;AAC1C,MAAA,MAAM,QAAA,GAAW,IAAI,gBAAA,CAAiB;AAAA,QACpC,UAAU,GAAA,CAAI,OAAA;AAAA,QACd,OAAA,EAAS,IAAA,CAAK,MAAA,CAAO,OAAA,IAAW,GAAA,CAAI,MAAA;AAAA,QACpC,OAAA,EAAS,IAAA,CAAK,UAAA,CAAW,GAAA,CAAI,OAAO;AAAA,OACrC,CAAA;AAED,MAAA,MAAM,SAAS,OAAA,EAAQ;AACvB,MAAA,MAAM,EAAE,QAAA,EAAS,GAAI,MAAM,SAAS,WAAA,EAAY;AAChD,MAAA,MAAM,OAAA,GAAU,QAAA,GAAW,CAAC,CAAA,EAAG,OAAA;AAC/B,MAAA,IAAI,CAAC,OAAA,EAAS;AACZ,QAAA,MAAM,IAAI,MAAM,2CAA2C,CAAA;AAAA,MAC7D;AACA,MAAA,IAAA,CAAK,QAAA,GAAW,QAAA;AAChB,MAAA,OAAO;AAAA,QACL,OAAA,EAAS,UAAU,OAAO,CAAA;AAAA,QAC1B,OAAA,EAAS;AAAA,UACP,UAAU,IAAA,CAAK,QAAA;AAAA;AAAA,UAEf,SAAS,GAAA,CAAI,OAAA;AAAA,UACb,SAAA,EAAW,KAAK,GAAA;AAAI,SACtB;AAAA,QACA,YAAA,EAAc,KAAK,eAAA;AAAgB,OACrC;AAAA,IACF,SAAS,GAAA,EAAK;AACZ,MAAA,MAAM,iCAAiC,GAAA,EAAK;AAAA,QAC1C,UAAU,IAAA,CAAK,QAAA;AAAA,QACf,KAAA,EAAO,SAAA;AAAA,QACP,SAAA,EAAW;AAAA,OACZ,CAAA;AAAA,IACH;AAAA,EACF;AAAA,EAEA,MAAM,UAAA,CAAW,IAAA,EAAsB,QAAA,EAAkC;AACvE,IAAA,IAAI,CAAC,KAAK,QAAA,EAAU;AACpB,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,CAAK,SAAS,UAAA,EAAW;AAAA,IACjC,CAAA,SAAE;AACA,MAAA,IAAA,CAAK,QAAA,GAAW,IAAA;AAAA,IAClB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,WAAA,CACE,IAAA,EACA,QAAA,EACA,OAAA,EACwB;AACxB,IAAA,OAAO,OAAA,CAAQ,MAAA;AAAA,MACb,IAAI,2BAAA,CAA4B,MAAA,CAAO,IAAA,CAAK,QAAQ,GAAG,aAAa;AAAA,KACtE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAM,iBAAA,CACJ,IAAA,EACA,QAAA,EACA,MAAA,EACoB;AACpB,IAAA,IAAI;AACF,MAAA,IAAI,CAAC,KAAK,QAAA,EAAU;AAClB,QAAA,MAAM,IAAI,MAAM,0BAA0B,CAAA;AAAA,MAC5C;AACA,MAAA,MAAM,QAAQ,MAAA,CAAO,QAAA;AACrB,MAAA,IACE,CAAC,KAAA,IACD,OAAO,KAAA,CAAM,SAAA,KAAc,QAAA,IAC3B,OAAO,KAAA,CAAM,YAAA,KAAiB,QAAA,IAC9B,OAAO,KAAA,CAAM,YAAY,QAAA,EACzB;AACA,QAAA,MAAM,IAAI,KAAA;AAAA,UACR;AAAA,SAEF;AAAA,MACF;AACA,MAAA,MAAM,IAAA,CAAK,SAAS,cAAA,CAAe;AAAA,QACjC,IAAA,EAAM,MAAM,IAAA,IAAQ,EAAA;AAAA,QACpB,SAAS,KAAA,CAAM,OAAA;AAAA,QACf,WAAW,KAAA,CAAM,SAAA;AAAA,QACjB,cAAc,KAAA,CAAM,YAAA;AAAA,QACpB,kBAAA,EAAoB,MAAM,kBAAA,IAAsB;AAAA,OACjD,CAAA;AAGD,MAAA,OAAO;AAAA,QACL,eAAA,EAAiB,iBAAA,CAAkB,KAAA,CAAM,SAAS,CAAA;AAAA,QAClD,WAAA,EAAa,KAAK,GAAA,EAAI;AAAA,QACtB,WAAW,KAAA,CAAM;AAAA,OACnB;AAAA,IACF,SAAS,GAAA,EAAK;AACZ,MAAA,MAAM,iCAAiC,GAAA,EAAK;AAAA,QAC1C,UAAU,IAAA,CAAK,QAAA;AAAA,QACf,KAAA,EAAO,mBAAA;AAAA,QACP,SAAA,EAAW;AAAA,OACZ,CAAA;AAAA,IACH;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,EAAA,CAAG,OAAyB,OAAA,EAAiD;AAC3E,IAAA,IAAI,KAAA,KAAU,UAAA,IAAc,CAAC,IAAA,CAAK,QAAA,EAAU;AAC1C,MAAA,OAAO,MAAM;AAAA,MAEb,CAAA;AAAA,IACF;AACA,IAAA,MAAM,MAAM,IAAA,CAAK,QAAA,CAAS,EAAA,CAAG,WAAA,EAAa,CAAC,CAAA,KAAM;AAC/C,MAAA,OAAA,CAAQ,EAAE,IAAA,EAAM,CAAA,CAAE,MAAM,MAAA,EAAQ,CAAA,CAAE,QAAQ,CAAA;AAAA,IAC5C,CAAC,CAAA;AACD,IAAA,OAAO,MAAM;AACX,MAAA,IAAI;AACF,QAAA,GAAA,EAAI;AAAA,MACN,CAAA,CAAA,MAAQ;AAAA,MAER;AAAA,IACF,CAAA;AAAA,EACF;AACF","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"]}
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\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 /**\n * Cantor8 is a HOSTED POPUP wallet: connect() opens the wallet at\n * wallet.dev.digik.cantor8.tech (devnet) or wallet.cantor8.tech (mainnet)\n * through the SDK's C8WalletProvider. Nothing of Cantor8 runs in THIS page, so\n * there is nothing here to detect.\n *\n * The SDK's discovery protocol has two sides. `announceC8Provider(get)` is the\n * DISPATCH side, called by a wallet that lives in the page to advertise a\n * provider factory; `onC8ProviderDiscovered(cb)` is the SUBSCRIBE side, called\n * by a dApp to hear such an announcement. A hosted popup on another origin never\n * calls `announceC8Provider` in our page, so subscribing and waiting for the\n * `c8#provider_discovery` event can only ever time out. That is precisely what\n * the previous strategy did, and it reported Cantor8 permanently unavailable,\n * which hid it from the picker.\n *\n * The right model is the gateway contract the official ProviderAdapter path uses\n * (see GenericDiscoveryAdapter.detectInstalled): a gateway is reachable wherever\n * it can be opened, so detect reports available and the REAL availability check\n * happens at connect(), when the popup opens. Walley, a popup wallet on that\n * generic path, works in our demos for exactly this reason.\n *\n * This is the SECOND detection strategy to be wrong here, both from the same\n * root cause: inferring the wallet's shape without the wallet in hand. First a\n * user-agent sniff mislabeled this desktop popup as a mobile wallet; then the\n * announcement wait assumed an in-page announcer that a hosted popup never\n * provides. Do not reintroduce a probe that depends on something being in the\n * page. If a future in-page Cantor8 ever announces over `c8#provider_discovery`,\n * it may be adopted as a fast path, but it must NEVER be the condition for\n * availability.\n *\n * detect still LOADS the SDK (the pre-fix detect did too; only its announcement\n * wait was wrong). This is deliberate warming, not detection: a bespoke adapter\n * does not get the SDK's popup-safe fast-path (that is for GenericDiscoveryAdapter),\n * so connect() reaches window.open only after awaits. detect runs at picker\n * render, off the click gesture, so the dynamic import resolves before the user\n * clicks; connect()'s `await loadC8()` is then a resolved microtask instead of a\n * cold import that would defer window.open past the gesture and let the browser\n * block the popup.\n */\n async detectInstalled(): Promise<AdapterDetectResult> {\n if (typeof window === 'undefined') {\n return { installed: false, reason: 'Browser environment required' };\n }\n // Warm the SDK module (see the warming note above). A load failure is not\n // fatal to availability; it surfaces at connect() where the real work happens.\n try {\n await loadC8();\n } catch {\n /* ignore; connect() surfaces a genuine SDK load failure */\n }\n return { installed: true };\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.3.0",
3
+ "version": "0.4.0",
4
4
  "sideEffects": false,
5
5
  "description": "Cantor8 (C8) Wallet adapter for PartyLayer",
6
6
  "main": "./dist/index.js",