@partylayer/adapter-cantor8 0.4.2 → 0.5.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/README.md +7 -0
- package/dist/index.js +10 -3
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +11 -4
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# @partylayer/adapter-cantor8
|
|
2
2
|
|
|
3
|
+
> **Default application integration:** The React kit already includes this compatibility
|
|
4
|
+
> runtime where applicable. Install `@partylayer/react @tanstack/react-query` in one
|
|
5
|
+
> command and use `PartyLayerKit` with `ConnectButton`; no per-wallet package
|
|
6
|
+
> installation is required. See [the quick start](https://partylayer.xyz/docs/quick-start).
|
|
7
|
+
> The instructions below are for explicitly using this standalone compatibility package.
|
|
8
|
+
> Native provider paths and limits are recorded in the [integration matrix](https://github.com/PartyLayer/PartyLayer/blob/main/docs/wallet-cip0103-matrix.md).
|
|
9
|
+
|
|
3
10
|
> **Legacy integration.** This package predates the generic bridge and is kept for
|
|
4
11
|
> compatibility; a new wallet should not copy this pattern. New wallets integrate
|
|
5
12
|
> through Path A or Path B with no PartyLayer-specific code, see
|
package/dist/index.js
CHANGED
|
@@ -70,13 +70,21 @@ var Cantor8Adapter = class {
|
|
|
70
70
|
*/
|
|
71
71
|
async detectInstalled() {
|
|
72
72
|
if (typeof window === "undefined") {
|
|
73
|
-
return {
|
|
73
|
+
return {
|
|
74
|
+
installed: false,
|
|
75
|
+
availability: { kind: "unknown", reason: "No browser environment" },
|
|
76
|
+
reason: "Browser environment required"
|
|
77
|
+
};
|
|
74
78
|
}
|
|
75
79
|
try {
|
|
76
80
|
await loadC8();
|
|
77
81
|
} catch {
|
|
78
82
|
}
|
|
79
|
-
return {
|
|
83
|
+
return {
|
|
84
|
+
installed: false,
|
|
85
|
+
availability: { kind: "no-local-install" },
|
|
86
|
+
reason: "Opens cantor8.tech in a new tab \u2014 nothing is installed locally"
|
|
87
|
+
};
|
|
80
88
|
}
|
|
81
89
|
async connect(ctx, _opts) {
|
|
82
90
|
try {
|
|
@@ -162,7 +170,6 @@ var Cantor8Adapter = class {
|
|
|
162
170
|
disclosedContracts: input.disclosedContracts ?? ""
|
|
163
171
|
});
|
|
164
172
|
return {
|
|
165
|
-
transactionHash: core.toTransactionHash(input.commandId),
|
|
166
173
|
submittedAt: Date.now(),
|
|
167
174
|
commandId: input.commandId
|
|
168
175
|
};
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
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"]}
|
|
1
|
+
{"version":3,"sources":["../src/cantor8-adapter.ts"],"names":["toWalletId","toPartyId","mapUnknownErrorToPartyLayerError","CapabilityNotSupportedError"],"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 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 {\n installed: false,\n availability: { kind: 'unknown', reason: 'No browser environment' },\n reason: 'Browser environment required',\n };\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 // Cantor8 is a HOSTED web wallet, not an extension: connecting opens a tab\n // on cantor8.tech. Answering `installed: true` put a ready-looking tile in\n // the picker for software that was never on the machine.\n return {\n installed: false,\n availability: { kind: 'no-local-install' },\n reason: 'Opens cantor8.tech in a new tab — nothing is installed locally',\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 ledger id; retain commandId only for correlation.\n // The confirmed ledger txId + status arrive via the txChanged event.\n return {\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
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { toWalletId, toPartyId, mapUnknownErrorToPartyLayerError, CapabilityNotSupportedError
|
|
1
|
+
import { toWalletId, toPartyId, mapUnknownErrorToPartyLayerError, CapabilityNotSupportedError } from '@partylayer/core';
|
|
2
2
|
|
|
3
3
|
// src/cantor8-adapter.ts
|
|
4
4
|
var c8ModulePromise = null;
|
|
@@ -68,13 +68,21 @@ var Cantor8Adapter = class {
|
|
|
68
68
|
*/
|
|
69
69
|
async detectInstalled() {
|
|
70
70
|
if (typeof window === "undefined") {
|
|
71
|
-
return {
|
|
71
|
+
return {
|
|
72
|
+
installed: false,
|
|
73
|
+
availability: { kind: "unknown", reason: "No browser environment" },
|
|
74
|
+
reason: "Browser environment required"
|
|
75
|
+
};
|
|
72
76
|
}
|
|
73
77
|
try {
|
|
74
78
|
await loadC8();
|
|
75
79
|
} catch {
|
|
76
80
|
}
|
|
77
|
-
return {
|
|
81
|
+
return {
|
|
82
|
+
installed: false,
|
|
83
|
+
availability: { kind: "no-local-install" },
|
|
84
|
+
reason: "Opens cantor8.tech in a new tab \u2014 nothing is installed locally"
|
|
85
|
+
};
|
|
78
86
|
}
|
|
79
87
|
async connect(ctx, _opts) {
|
|
80
88
|
try {
|
|
@@ -160,7 +168,6 @@ var Cantor8Adapter = class {
|
|
|
160
168
|
disclosedContracts: input.disclosedContracts ?? ""
|
|
161
169
|
});
|
|
162
170
|
return {
|
|
163
|
-
transactionHash: toTransactionHash(input.commandId),
|
|
164
171
|
submittedAt: Date.now(),
|
|
165
172
|
commandId: input.commandId
|
|
166
173
|
};
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
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"]}
|
|
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 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 {\n installed: false,\n availability: { kind: 'unknown', reason: 'No browser environment' },\n reason: 'Browser environment required',\n };\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 // Cantor8 is a HOSTED web wallet, not an extension: connecting opens a tab\n // on cantor8.tech. Answering `installed: true` put a ready-looking tile in\n // the picker for software that was never on the machine.\n return {\n installed: false,\n availability: { kind: 'no-local-install' },\n reason: 'Opens cantor8.tech in a new tab — nothing is installed locally',\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 ledger id; retain commandId only for correlation.\n // The confirmed ledger txId + status arrive via the txChanged event.\n return {\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
|
+
"version": "0.5.0",
|
|
4
4
|
"sideEffects": false,
|
|
5
5
|
"description": "Cantor8 (C8) Wallet adapter for PartyLayer",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@cantor8/wallet-connect-sdk": "^0.4.0",
|
|
37
|
-
"@partylayer/core": "^0.
|
|
37
|
+
"@partylayer/core": "^0.15.0"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@types/node": "^20.11.0",
|