@partylayer/adapter-cantor8 0.2.2
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/LICENSE +21 -0
- package/dist/index.d.mts +97 -0
- package/dist/index.d.ts +97 -0
- package/dist/index.js +313 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +311 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +47 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 CantonConnect
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import * as _partylayer_core from '@partylayer/core';
|
|
2
|
+
import { ConnectRequest, ConnectResponse, SignRequest, SignResponse, JobStatus, WalletAdapter, CapabilityKey, AdapterDetectResult, AdapterContext, AdapterConnectResult, SignMessageParams, SignTransactionParams } from '@partylayer/core';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Cantor8 Vendor Integration Module
|
|
6
|
+
*
|
|
7
|
+
* This module abstracts vendor-specific endpoints and can be swapped
|
|
8
|
+
* without breaking the adapter API.
|
|
9
|
+
*
|
|
10
|
+
* References:
|
|
11
|
+
* - Cantor8 ecosystem: https://www.canton.network/ecosystem/cantor8
|
|
12
|
+
* - Cantor8 site: https://cantor8.tech/about
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Vendor configuration
|
|
17
|
+
*/
|
|
18
|
+
interface Cantor8VendorConfig {
|
|
19
|
+
/** Deep link scheme (e.g., "cantor8") */
|
|
20
|
+
deepLinkScheme?: string;
|
|
21
|
+
/** Universal link base URL (e.g., "https://app.cantor8.tech") */
|
|
22
|
+
universalLinkBase?: string;
|
|
23
|
+
/** Connect endpoint path */
|
|
24
|
+
connectEndpoint?: string;
|
|
25
|
+
/** Sign endpoint path */
|
|
26
|
+
signEndpoint?: string;
|
|
27
|
+
/** Job status endpoint path (for async approvals) */
|
|
28
|
+
statusEndpoint?: string;
|
|
29
|
+
/** Redirect URI for callbacks */
|
|
30
|
+
redirectUri?: string;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Vendor module interface
|
|
34
|
+
*
|
|
35
|
+
* Implementations can be swapped without changing adapter code.
|
|
36
|
+
*/
|
|
37
|
+
interface Cantor8VendorModule {
|
|
38
|
+
/**
|
|
39
|
+
* Create connect URL
|
|
40
|
+
*/
|
|
41
|
+
createConnectUrl(request: ConnectRequest, config: Cantor8VendorConfig): string;
|
|
42
|
+
/**
|
|
43
|
+
* Parse connect callback
|
|
44
|
+
*/
|
|
45
|
+
parseConnectCallback(callbackData: unknown, expectedState: string): ConnectResponse;
|
|
46
|
+
/**
|
|
47
|
+
* Create sign URL
|
|
48
|
+
*/
|
|
49
|
+
createSignUrl(request: SignRequest, config: Cantor8VendorConfig): string;
|
|
50
|
+
/**
|
|
51
|
+
* Parse sign callback
|
|
52
|
+
*/
|
|
53
|
+
parseSignCallback(callbackData: unknown, expectedState: string): SignResponse;
|
|
54
|
+
/**
|
|
55
|
+
* Poll job status (optional, for async approvals)
|
|
56
|
+
*/
|
|
57
|
+
pollJobStatus?(jobId: string, statusUrl: string, timeoutMs: number): Promise<JobStatus>;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Cantor8 adapter configuration
|
|
62
|
+
*/
|
|
63
|
+
interface Cantor8AdapterConfig {
|
|
64
|
+
/** Vendor module (defaults to stub) */
|
|
65
|
+
vendorModule?: Cantor8VendorModule;
|
|
66
|
+
/** Vendor configuration */
|
|
67
|
+
vendorConfig?: Cantor8VendorConfig;
|
|
68
|
+
/** Use mock transport in development */
|
|
69
|
+
useMockTransport?: boolean;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Cantor8 Wallet Adapter
|
|
73
|
+
*/
|
|
74
|
+
declare class Cantor8Adapter implements WalletAdapter {
|
|
75
|
+
readonly walletId: _partylayer_core.WalletId;
|
|
76
|
+
readonly name = "Cantor8";
|
|
77
|
+
private vendorModule;
|
|
78
|
+
private vendorConfig;
|
|
79
|
+
private transport;
|
|
80
|
+
constructor(config?: Cantor8AdapterConfig);
|
|
81
|
+
getCapabilities(): CapabilityKey[];
|
|
82
|
+
detectInstalled(): Promise<AdapterDetectResult>;
|
|
83
|
+
connect(ctx: AdapterContext, opts?: {
|
|
84
|
+
timeoutMs?: number;
|
|
85
|
+
partyId?: _partylayer_core.PartyId;
|
|
86
|
+
}): Promise<AdapterConnectResult>;
|
|
87
|
+
disconnect(_ctx: AdapterContext, _session: _partylayer_core.Session): Promise<void>;
|
|
88
|
+
restore(_ctx: AdapterContext, persisted: _partylayer_core.PersistedSession): Promise<_partylayer_core.Session | null>;
|
|
89
|
+
signMessage(ctx: AdapterContext, session: _partylayer_core.Session, params: SignMessageParams): Promise<_partylayer_core.SignedMessage>;
|
|
90
|
+
signTransaction(ctx: AdapterContext, session: _partylayer_core.Session, params: SignTransactionParams): Promise<_partylayer_core.SignedTransaction>;
|
|
91
|
+
/**
|
|
92
|
+
* Generate random state nonce
|
|
93
|
+
*/
|
|
94
|
+
private generateState;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export { Cantor8Adapter, type Cantor8AdapterConfig };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import * as _partylayer_core from '@partylayer/core';
|
|
2
|
+
import { ConnectRequest, ConnectResponse, SignRequest, SignResponse, JobStatus, WalletAdapter, CapabilityKey, AdapterDetectResult, AdapterContext, AdapterConnectResult, SignMessageParams, SignTransactionParams } from '@partylayer/core';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Cantor8 Vendor Integration Module
|
|
6
|
+
*
|
|
7
|
+
* This module abstracts vendor-specific endpoints and can be swapped
|
|
8
|
+
* without breaking the adapter API.
|
|
9
|
+
*
|
|
10
|
+
* References:
|
|
11
|
+
* - Cantor8 ecosystem: https://www.canton.network/ecosystem/cantor8
|
|
12
|
+
* - Cantor8 site: https://cantor8.tech/about
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Vendor configuration
|
|
17
|
+
*/
|
|
18
|
+
interface Cantor8VendorConfig {
|
|
19
|
+
/** Deep link scheme (e.g., "cantor8") */
|
|
20
|
+
deepLinkScheme?: string;
|
|
21
|
+
/** Universal link base URL (e.g., "https://app.cantor8.tech") */
|
|
22
|
+
universalLinkBase?: string;
|
|
23
|
+
/** Connect endpoint path */
|
|
24
|
+
connectEndpoint?: string;
|
|
25
|
+
/** Sign endpoint path */
|
|
26
|
+
signEndpoint?: string;
|
|
27
|
+
/** Job status endpoint path (for async approvals) */
|
|
28
|
+
statusEndpoint?: string;
|
|
29
|
+
/** Redirect URI for callbacks */
|
|
30
|
+
redirectUri?: string;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Vendor module interface
|
|
34
|
+
*
|
|
35
|
+
* Implementations can be swapped without changing adapter code.
|
|
36
|
+
*/
|
|
37
|
+
interface Cantor8VendorModule {
|
|
38
|
+
/**
|
|
39
|
+
* Create connect URL
|
|
40
|
+
*/
|
|
41
|
+
createConnectUrl(request: ConnectRequest, config: Cantor8VendorConfig): string;
|
|
42
|
+
/**
|
|
43
|
+
* Parse connect callback
|
|
44
|
+
*/
|
|
45
|
+
parseConnectCallback(callbackData: unknown, expectedState: string): ConnectResponse;
|
|
46
|
+
/**
|
|
47
|
+
* Create sign URL
|
|
48
|
+
*/
|
|
49
|
+
createSignUrl(request: SignRequest, config: Cantor8VendorConfig): string;
|
|
50
|
+
/**
|
|
51
|
+
* Parse sign callback
|
|
52
|
+
*/
|
|
53
|
+
parseSignCallback(callbackData: unknown, expectedState: string): SignResponse;
|
|
54
|
+
/**
|
|
55
|
+
* Poll job status (optional, for async approvals)
|
|
56
|
+
*/
|
|
57
|
+
pollJobStatus?(jobId: string, statusUrl: string, timeoutMs: number): Promise<JobStatus>;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Cantor8 adapter configuration
|
|
62
|
+
*/
|
|
63
|
+
interface Cantor8AdapterConfig {
|
|
64
|
+
/** Vendor module (defaults to stub) */
|
|
65
|
+
vendorModule?: Cantor8VendorModule;
|
|
66
|
+
/** Vendor configuration */
|
|
67
|
+
vendorConfig?: Cantor8VendorConfig;
|
|
68
|
+
/** Use mock transport in development */
|
|
69
|
+
useMockTransport?: boolean;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Cantor8 Wallet Adapter
|
|
73
|
+
*/
|
|
74
|
+
declare class Cantor8Adapter implements WalletAdapter {
|
|
75
|
+
readonly walletId: _partylayer_core.WalletId;
|
|
76
|
+
readonly name = "Cantor8";
|
|
77
|
+
private vendorModule;
|
|
78
|
+
private vendorConfig;
|
|
79
|
+
private transport;
|
|
80
|
+
constructor(config?: Cantor8AdapterConfig);
|
|
81
|
+
getCapabilities(): CapabilityKey[];
|
|
82
|
+
detectInstalled(): Promise<AdapterDetectResult>;
|
|
83
|
+
connect(ctx: AdapterContext, opts?: {
|
|
84
|
+
timeoutMs?: number;
|
|
85
|
+
partyId?: _partylayer_core.PartyId;
|
|
86
|
+
}): Promise<AdapterConnectResult>;
|
|
87
|
+
disconnect(_ctx: AdapterContext, _session: _partylayer_core.Session): Promise<void>;
|
|
88
|
+
restore(_ctx: AdapterContext, persisted: _partylayer_core.PersistedSession): Promise<_partylayer_core.Session | null>;
|
|
89
|
+
signMessage(ctx: AdapterContext, session: _partylayer_core.Session, params: SignMessageParams): Promise<_partylayer_core.SignedMessage>;
|
|
90
|
+
signTransaction(ctx: AdapterContext, session: _partylayer_core.Session, params: SignTransactionParams): Promise<_partylayer_core.SignedTransaction>;
|
|
91
|
+
/**
|
|
92
|
+
* Generate random state nonce
|
|
93
|
+
*/
|
|
94
|
+
private generateState;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export { Cantor8Adapter, type Cantor8AdapterConfig };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var core = require('@partylayer/core');
|
|
4
|
+
|
|
5
|
+
// src/cantor8-adapter.ts
|
|
6
|
+
var StubCantor8VendorModule = class {
|
|
7
|
+
createConnectUrl(request, config) {
|
|
8
|
+
if (config.universalLinkBase) {
|
|
9
|
+
const endpoint = config.connectEndpoint || "/connect";
|
|
10
|
+
const url = new URL(endpoint, config.universalLinkBase);
|
|
11
|
+
Object.entries(request).forEach(([key, value]) => {
|
|
12
|
+
if (value !== void 0) {
|
|
13
|
+
url.searchParams.set(key, typeof value === "string" ? value : JSON.stringify(value));
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
return url.toString();
|
|
17
|
+
}
|
|
18
|
+
if (config.deepLinkScheme) {
|
|
19
|
+
const params = new URLSearchParams();
|
|
20
|
+
Object.entries(request).forEach(([key, value]) => {
|
|
21
|
+
if (value !== void 0) {
|
|
22
|
+
params.set(key, typeof value === "string" ? value : JSON.stringify(value));
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
return `${config.deepLinkScheme}://connect?${params.toString()}`;
|
|
26
|
+
}
|
|
27
|
+
throw new Error(
|
|
28
|
+
"Cantor8 vendor not configured. Please set deepLinkScheme or universalLinkBase in adapter config."
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
parseConnectCallback(callbackData, expectedState) {
|
|
32
|
+
const data = callbackData;
|
|
33
|
+
if (data.state !== expectedState) {
|
|
34
|
+
throw new Error("State mismatch in callback");
|
|
35
|
+
}
|
|
36
|
+
return {
|
|
37
|
+
state: String(data.state),
|
|
38
|
+
partyId: data.partyId ? core.toPartyId(String(data.partyId)) : void 0,
|
|
39
|
+
sessionToken: data.sessionToken ? String(data.sessionToken) : void 0,
|
|
40
|
+
expiresAt: data.expiresAt ? Number(data.expiresAt) : void 0,
|
|
41
|
+
capabilities: data.capabilities ? Array.isArray(data.capabilities) ? data.capabilities.map(String) : [] : void 0,
|
|
42
|
+
error: data.error ? {
|
|
43
|
+
code: String(data.error.code || "UNKNOWN"),
|
|
44
|
+
message: String(data.error.message || "Unknown error")
|
|
45
|
+
} : void 0
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
createSignUrl(request, config) {
|
|
49
|
+
if (config.universalLinkBase) {
|
|
50
|
+
const endpoint = config.signEndpoint || "/sign";
|
|
51
|
+
const url = new URL(endpoint, config.universalLinkBase);
|
|
52
|
+
Object.entries(request).forEach(([key, value]) => {
|
|
53
|
+
if (value !== void 0) {
|
|
54
|
+
url.searchParams.set(key, typeof value === "string" ? value : JSON.stringify(value));
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
return url.toString();
|
|
58
|
+
}
|
|
59
|
+
if (config.deepLinkScheme) {
|
|
60
|
+
const params = new URLSearchParams();
|
|
61
|
+
Object.entries(request).forEach(([key, value]) => {
|
|
62
|
+
if (value !== void 0) {
|
|
63
|
+
params.set(key, typeof value === "string" ? value : JSON.stringify(value));
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
return `${config.deepLinkScheme}://sign?${params.toString()}`;
|
|
67
|
+
}
|
|
68
|
+
throw new Error("Cantor8 vendor not configured");
|
|
69
|
+
}
|
|
70
|
+
parseSignCallback(callbackData, expectedState) {
|
|
71
|
+
const data = callbackData;
|
|
72
|
+
if (data.state !== expectedState) {
|
|
73
|
+
throw new Error("State mismatch in callback");
|
|
74
|
+
}
|
|
75
|
+
return {
|
|
76
|
+
state: String(data.state),
|
|
77
|
+
signature: data.signature ? String(data.signature) : void 0,
|
|
78
|
+
transactionHash: data.transactionHash ? String(data.transactionHash) : void 0,
|
|
79
|
+
jobId: data.jobId ? String(data.jobId) : void 0,
|
|
80
|
+
error: data.error ? {
|
|
81
|
+
code: String(data.error.code || "UNKNOWN"),
|
|
82
|
+
message: String(data.error.message || "Unknown error")
|
|
83
|
+
} : void 0
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
// src/cantor8-adapter.ts
|
|
89
|
+
var Cantor8Adapter = class {
|
|
90
|
+
walletId = core.toWalletId("cantor8");
|
|
91
|
+
name = "Cantor8";
|
|
92
|
+
vendorModule;
|
|
93
|
+
vendorConfig;
|
|
94
|
+
transport;
|
|
95
|
+
constructor(config = {}) {
|
|
96
|
+
this.vendorModule = config.vendorModule || new StubCantor8VendorModule();
|
|
97
|
+
this.vendorConfig = config.vendorConfig || {};
|
|
98
|
+
if (config.useMockTransport || process.env.NODE_ENV === "development") {
|
|
99
|
+
this.transport = new core.MockTransport();
|
|
100
|
+
} else {
|
|
101
|
+
this.transport = new core.DeepLinkTransport();
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
getCapabilities() {
|
|
105
|
+
return [
|
|
106
|
+
"connect",
|
|
107
|
+
"disconnect",
|
|
108
|
+
"deeplink",
|
|
109
|
+
"signMessage",
|
|
110
|
+
"signTransaction"
|
|
111
|
+
// restore depends on sessionToken support
|
|
112
|
+
];
|
|
113
|
+
}
|
|
114
|
+
detectInstalled() {
|
|
115
|
+
if (typeof window === "undefined") {
|
|
116
|
+
return Promise.resolve({ installed: false, reason: "Browser environment required" });
|
|
117
|
+
}
|
|
118
|
+
const isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
|
|
119
|
+
return Promise.resolve({
|
|
120
|
+
installed: isMobile,
|
|
121
|
+
reason: isMobile ? void 0 : "Cantor8 is a mobile wallet"
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
async connect(ctx, opts) {
|
|
125
|
+
try {
|
|
126
|
+
const state = this.generateState();
|
|
127
|
+
const redirectUri = this.vendorConfig.redirectUri || `${ctx.origin}/callback`;
|
|
128
|
+
const request = {
|
|
129
|
+
appName: ctx.appName,
|
|
130
|
+
origin: ctx.origin,
|
|
131
|
+
network: ctx.network,
|
|
132
|
+
requestedCapabilities: void 0,
|
|
133
|
+
// Cantor8 doesn't support capability filtering yet
|
|
134
|
+
state,
|
|
135
|
+
redirectUri
|
|
136
|
+
};
|
|
137
|
+
const connectUrl = this.vendorModule.createConnectUrl(request, this.vendorConfig);
|
|
138
|
+
const transportOptions = {
|
|
139
|
+
timeoutMs: opts?.timeoutMs || 6e4,
|
|
140
|
+
allowedOrigins: [ctx.origin],
|
|
141
|
+
origin: ctx.origin
|
|
142
|
+
};
|
|
143
|
+
const response = await this.transport.openConnectRequest(
|
|
144
|
+
connectUrl,
|
|
145
|
+
request,
|
|
146
|
+
transportOptions
|
|
147
|
+
);
|
|
148
|
+
if (response.error) {
|
|
149
|
+
if (response.error.code === "USER_REJECTED" || response.error.code === "CANCELLED") {
|
|
150
|
+
throw new core.UserRejectedError("User rejected connection");
|
|
151
|
+
}
|
|
152
|
+
throw new Error(response.error.message || "Connection failed");
|
|
153
|
+
}
|
|
154
|
+
if (!response.partyId) {
|
|
155
|
+
throw new Error("No partyId in response");
|
|
156
|
+
}
|
|
157
|
+
return {
|
|
158
|
+
partyId: response.partyId,
|
|
159
|
+
session: {
|
|
160
|
+
walletId: this.walletId,
|
|
161
|
+
network: ctx.network,
|
|
162
|
+
createdAt: Date.now(),
|
|
163
|
+
expiresAt: response.expiresAt,
|
|
164
|
+
capabilitiesSnapshot: response.capabilities || ["connect", "signMessage"],
|
|
165
|
+
metadata: {
|
|
166
|
+
sessionToken: response.sessionToken || ""
|
|
167
|
+
}
|
|
168
|
+
},
|
|
169
|
+
capabilities: response.capabilities || ["connect", "signMessage"]
|
|
170
|
+
};
|
|
171
|
+
} catch (err) {
|
|
172
|
+
throw core.mapUnknownErrorToPartyLayerError(err, {
|
|
173
|
+
walletId: this.walletId,
|
|
174
|
+
phase: "connect",
|
|
175
|
+
transport: "deeplink"
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
disconnect(_ctx, _session) {
|
|
180
|
+
if (_session.metadata?.sessionToken) ;
|
|
181
|
+
return Promise.resolve();
|
|
182
|
+
}
|
|
183
|
+
restore(_ctx, persisted) {
|
|
184
|
+
const sessionToken = persisted.metadata?.sessionToken;
|
|
185
|
+
if (typeof sessionToken !== "string") {
|
|
186
|
+
return Promise.resolve(null);
|
|
187
|
+
}
|
|
188
|
+
if (persisted.expiresAt && Date.now() >= persisted.expiresAt) {
|
|
189
|
+
return Promise.resolve(null);
|
|
190
|
+
}
|
|
191
|
+
return Promise.resolve({
|
|
192
|
+
...persisted,
|
|
193
|
+
walletId: this.walletId
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
async signMessage(ctx, session, params) {
|
|
197
|
+
try {
|
|
198
|
+
const state = this.generateState();
|
|
199
|
+
const redirectUri = this.vendorConfig.redirectUri || `${ctx.origin}/callback`;
|
|
200
|
+
const request = {
|
|
201
|
+
message: params.message,
|
|
202
|
+
state,
|
|
203
|
+
redirectUri
|
|
204
|
+
};
|
|
205
|
+
const signUrl = this.vendorModule.createSignUrl(request, this.vendorConfig);
|
|
206
|
+
const transportOptions = {
|
|
207
|
+
timeoutMs: 6e4,
|
|
208
|
+
allowedOrigins: [ctx.origin],
|
|
209
|
+
origin: ctx.origin
|
|
210
|
+
};
|
|
211
|
+
const response = await this.transport.openSignRequest(
|
|
212
|
+
signUrl,
|
|
213
|
+
request,
|
|
214
|
+
transportOptions
|
|
215
|
+
);
|
|
216
|
+
if (response.error) {
|
|
217
|
+
if (response.error.code === "USER_REJECTED") {
|
|
218
|
+
throw new core.UserRejectedError("User rejected signing");
|
|
219
|
+
}
|
|
220
|
+
throw new Error(response.error.message || "Signing failed");
|
|
221
|
+
}
|
|
222
|
+
if (!response.signature) {
|
|
223
|
+
throw new Error("No signature in response");
|
|
224
|
+
}
|
|
225
|
+
return {
|
|
226
|
+
message: params.message,
|
|
227
|
+
signature: core.toSignature(response.signature),
|
|
228
|
+
partyId: session.partyId
|
|
229
|
+
};
|
|
230
|
+
} catch (err) {
|
|
231
|
+
throw core.mapUnknownErrorToPartyLayerError(err, {
|
|
232
|
+
walletId: this.walletId,
|
|
233
|
+
phase: "signMessage",
|
|
234
|
+
transport: "deeplink"
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
async signTransaction(ctx, session, params) {
|
|
239
|
+
try {
|
|
240
|
+
const state = this.generateState();
|
|
241
|
+
const redirectUri = this.vendorConfig.redirectUri || `${ctx.origin}/callback`;
|
|
242
|
+
const request = {
|
|
243
|
+
transaction: params.tx,
|
|
244
|
+
state,
|
|
245
|
+
redirectUri
|
|
246
|
+
};
|
|
247
|
+
const signUrl = this.vendorModule.createSignUrl(request, this.vendorConfig);
|
|
248
|
+
const transportOptions = {
|
|
249
|
+
timeoutMs: 6e4,
|
|
250
|
+
allowedOrigins: [ctx.origin],
|
|
251
|
+
origin: ctx.origin
|
|
252
|
+
};
|
|
253
|
+
const response = await this.transport.openSignRequest(
|
|
254
|
+
signUrl,
|
|
255
|
+
request,
|
|
256
|
+
transportOptions
|
|
257
|
+
);
|
|
258
|
+
if (response.error) {
|
|
259
|
+
if (response.error.code === "USER_REJECTED") {
|
|
260
|
+
throw new core.UserRejectedError("User rejected signing");
|
|
261
|
+
}
|
|
262
|
+
throw new Error(response.error.message || "Signing failed");
|
|
263
|
+
}
|
|
264
|
+
if (response.jobId && this.vendorModule.pollJobStatus) {
|
|
265
|
+
const statusUrl = this.vendorConfig.statusEndpoint || "";
|
|
266
|
+
const jobStatus = await this.vendorModule.pollJobStatus(
|
|
267
|
+
response.jobId,
|
|
268
|
+
statusUrl,
|
|
269
|
+
6e4
|
|
270
|
+
);
|
|
271
|
+
if (jobStatus.status === "denied") {
|
|
272
|
+
throw new core.UserRejectedError("Transaction signing denied");
|
|
273
|
+
}
|
|
274
|
+
if (jobStatus.status === "approved" && jobStatus.result?.signature) {
|
|
275
|
+
const signedTx2 = typeof params.tx === "object" && params.tx !== null ? { ...params.tx, signature: jobStatus.result.signature } : { tx: params.tx, signature: jobStatus.result.signature };
|
|
276
|
+
return {
|
|
277
|
+
signedTx: signedTx2,
|
|
278
|
+
transactionHash: jobStatus.result.transactionHash ? core.toTransactionHash(jobStatus.result.transactionHash) : core.toTransactionHash("pending"),
|
|
279
|
+
partyId: session.partyId
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
throw new Error("Job not completed");
|
|
283
|
+
}
|
|
284
|
+
if (!response.signature) {
|
|
285
|
+
throw new Error("No signature in response");
|
|
286
|
+
}
|
|
287
|
+
const signedTx = typeof params.tx === "object" && params.tx !== null ? { ...params.tx, signature: response.signature } : { tx: params.tx, signature: response.signature };
|
|
288
|
+
return {
|
|
289
|
+
signedTx,
|
|
290
|
+
transactionHash: response.transactionHash ? core.toTransactionHash(response.transactionHash) : core.toTransactionHash("pending"),
|
|
291
|
+
partyId: session.partyId
|
|
292
|
+
};
|
|
293
|
+
} catch (err) {
|
|
294
|
+
throw core.mapUnknownErrorToPartyLayerError(err, {
|
|
295
|
+
walletId: this.walletId,
|
|
296
|
+
phase: "signTransaction",
|
|
297
|
+
transport: "deeplink"
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Generate random state nonce
|
|
303
|
+
*/
|
|
304
|
+
generateState() {
|
|
305
|
+
const array = new Uint8Array(32);
|
|
306
|
+
crypto.getRandomValues(array);
|
|
307
|
+
return Array.from(array, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
308
|
+
}
|
|
309
|
+
};
|
|
310
|
+
|
|
311
|
+
exports.Cantor8Adapter = Cantor8Adapter;
|
|
312
|
+
//# sourceMappingURL=index.js.map
|
|
313
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/vendor.ts","../src/cantor8-adapter.ts"],"names":["toPartyId","toWalletId","MockTransport","DeepLinkTransport","UserRejectedError","mapUnknownErrorToPartyLayerError","toSignature","signedTx","toTransactionHash"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Cantor8 Vendor Integration Module\n * \n * This module abstracts vendor-specific endpoints and can be swapped\n * without breaking the adapter API.\n * \n * References:\n * - Cantor8 ecosystem: https://www.canton.network/ecosystem/cantor8\n * - Cantor8 site: https://cantor8.tech/about\n */\n\nimport type {\n ConnectRequest,\n ConnectResponse,\n SignRequest,\n SignResponse,\n JobStatus,\n} from '@partylayer/core';\nimport { toPartyId } from '@partylayer/core';\n\n/**\n * Vendor configuration\n */\nexport interface Cantor8VendorConfig {\n /** Deep link scheme (e.g., \"cantor8\") */\n deepLinkScheme?: string;\n /** Universal link base URL (e.g., \"https://app.cantor8.tech\") */\n universalLinkBase?: string;\n /** Connect endpoint path */\n connectEndpoint?: string;\n /** Sign endpoint path */\n signEndpoint?: string;\n /** Job status endpoint path (for async approvals) */\n statusEndpoint?: string;\n /** Redirect URI for callbacks */\n redirectUri?: string;\n}\n\n/**\n * Vendor module interface\n * \n * Implementations can be swapped without changing adapter code.\n */\nexport interface Cantor8VendorModule {\n /**\n * Create connect URL\n */\n createConnectUrl(request: ConnectRequest, config: Cantor8VendorConfig): string;\n\n /**\n * Parse connect callback\n */\n parseConnectCallback(\n callbackData: unknown,\n expectedState: string\n ): ConnectResponse;\n\n /**\n * Create sign URL\n */\n createSignUrl(request: SignRequest, config: Cantor8VendorConfig): string;\n\n /**\n * Parse sign callback\n */\n parseSignCallback(\n callbackData: unknown,\n expectedState: string\n ): SignResponse;\n\n /**\n * Poll job status (optional, for async approvals)\n */\n pollJobStatus?(\n jobId: string,\n statusUrl: string,\n timeoutMs: number\n ): Promise<JobStatus>;\n}\n\n/**\n * Default/stub vendor module\n * \n * This implementation provides a structured interface but throws\n * NotConfiguredError with clear instructions when vendor endpoints\n * are not configured.\n */\nexport class StubCantor8VendorModule implements Cantor8VendorModule {\n createConnectUrl(request: ConnectRequest, config: Cantor8VendorConfig): string {\n // Prefer universal link if configured\n if (config.universalLinkBase) {\n const endpoint = config.connectEndpoint || '/connect';\n const url = new URL(endpoint, config.universalLinkBase);\n Object.entries(request).forEach(([key, value]) => {\n if (value !== undefined) {\n url.searchParams.set(key, typeof value === 'string' ? value : JSON.stringify(value));\n }\n });\n return url.toString();\n }\n\n // Fallback to deep link scheme\n if (config.deepLinkScheme) {\n const params = new URLSearchParams();\n Object.entries(request).forEach(([key, value]) => {\n if (value !== undefined) {\n params.set(key, typeof value === 'string' ? value : JSON.stringify(value));\n }\n });\n return `${config.deepLinkScheme}://connect?${params.toString()}`;\n }\n\n throw new Error(\n 'Cantor8 vendor not configured. Please set deepLinkScheme or universalLinkBase in adapter config.'\n );\n }\n\n parseConnectCallback(\n callbackData: unknown,\n expectedState: string\n ): ConnectResponse {\n // Parse callback data (could be URL params, postMessage, etc.)\n const data = callbackData as Record<string, unknown>;\n\n // Validate state\n if (data.state !== expectedState) {\n throw new Error('State mismatch in callback');\n }\n\n // Return response\n return {\n state: String(data.state),\n partyId: data.partyId ? toPartyId(String(data.partyId)) : undefined,\n sessionToken: data.sessionToken ? String(data.sessionToken) : undefined,\n expiresAt: data.expiresAt ? Number(data.expiresAt) : undefined,\n capabilities: data.capabilities\n ? (Array.isArray(data.capabilities) ? data.capabilities.map(String) : [])\n : undefined,\n error: data.error\n ? {\n code: String((data.error as Record<string, unknown>).code || 'UNKNOWN'),\n message: String((data.error as Record<string, unknown>).message || 'Unknown error'),\n }\n : undefined,\n };\n }\n\n createSignUrl(request: SignRequest, config: Cantor8VendorConfig): string {\n if (config.universalLinkBase) {\n const endpoint = config.signEndpoint || '/sign';\n const url = new URL(endpoint, config.universalLinkBase);\n Object.entries(request).forEach(([key, value]) => {\n if (value !== undefined) {\n url.searchParams.set(key, typeof value === 'string' ? value : JSON.stringify(value));\n }\n });\n return url.toString();\n }\n\n if (config.deepLinkScheme) {\n const params = new URLSearchParams();\n Object.entries(request).forEach(([key, value]) => {\n if (value !== undefined) {\n params.set(key, typeof value === 'string' ? value : JSON.stringify(value));\n }\n });\n return `${config.deepLinkScheme}://sign?${params.toString()}`;\n }\n\n throw new Error('Cantor8 vendor not configured');\n }\n\n parseSignCallback(\n callbackData: unknown,\n expectedState: string\n ): SignResponse {\n const data = callbackData as Record<string, unknown>;\n\n if (data.state !== expectedState) {\n throw new Error('State mismatch in callback');\n }\n\n return {\n state: String(data.state),\n signature: data.signature ? String(data.signature) : undefined,\n transactionHash: data.transactionHash ? String(data.transactionHash) : undefined,\n jobId: data.jobId ? String(data.jobId) : undefined,\n error: data.error\n ? {\n code: String((data.error as Record<string, unknown>).code || 'UNKNOWN'),\n message: String((data.error as Record<string, unknown>).message || 'Unknown error'),\n }\n : undefined,\n };\n }\n}\n","/**\n * Cantor8 (C8) Wallet Adapter\n * \n * Implements WalletAdapter interface for Cantor8 wallet using deep link transport.\n * \n * References:\n * - Cantor8 ecosystem: https://www.canton.network/ecosystem/cantor8\n * - Cantor8 site: https://cantor8.tech/about\n * - Wallet Integration Guide: https://docs.digitalasset.com/integrate/devnet/index.html\n */\n\nimport type {\n WalletAdapter,\n AdapterContext,\n AdapterDetectResult,\n AdapterConnectResult,\n SignMessageParams,\n SignTransactionParams,\n} from '@partylayer/core';\nimport {\n toWalletId,\n toSignature,\n toTransactionHash,\n UserRejectedError,\n mapUnknownErrorToPartyLayerError,\n type CapabilityKey,\n} from '@partylayer/core';\nimport { DeepLinkTransport, MockTransport } from '@partylayer/core';\nimport type {\n Cantor8VendorModule,\n Cantor8VendorConfig,\n} from './vendor';\nimport {\n StubCantor8VendorModule,\n} from './vendor';\n\n/**\n * Cantor8 adapter configuration\n */\nexport interface Cantor8AdapterConfig {\n /** Vendor module (defaults to stub) */\n vendorModule?: Cantor8VendorModule;\n /** Vendor configuration */\n vendorConfig?: Cantor8VendorConfig;\n /** Use mock transport in development */\n useMockTransport?: boolean;\n}\n\n/**\n * Cantor8 Wallet Adapter\n */\nexport class Cantor8Adapter implements WalletAdapter {\n readonly walletId = toWalletId('cantor8');\n readonly name = 'Cantor8';\n\n private vendorModule: Cantor8VendorModule;\n private vendorConfig: Cantor8VendorConfig;\n private transport: DeepLinkTransport | MockTransport;\n\n constructor(config: Cantor8AdapterConfig = {}) {\n this.vendorModule = config.vendorModule || new StubCantor8VendorModule();\n this.vendorConfig = config.vendorConfig || {};\n \n // Use mock transport in development if configured\n if (config.useMockTransport || process.env.NODE_ENV === 'development') {\n this.transport = new MockTransport();\n } else {\n this.transport = new DeepLinkTransport();\n }\n }\n\n getCapabilities(): CapabilityKey[] {\n return [\n 'connect',\n 'disconnect',\n 'deeplink',\n 'signMessage',\n 'signTransaction',\n // restore depends on sessionToken support\n ];\n }\n\n detectInstalled(): Promise<AdapterDetectResult> {\n // Cantor8 is a mobile wallet - detection is not straightforward\n // We can check for deep link support or user agent hints\n if (typeof window === 'undefined') {\n return Promise.resolve({ installed: false, reason: 'Browser environment required' });\n }\n\n // Check if device supports deep links (mobile)\n const isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);\n \n // For now, assume installed if mobile device\n // In production, might check for specific user agent or other hints\n return Promise.resolve({\n installed: isMobile,\n reason: isMobile ? undefined : 'Cantor8 is a mobile wallet',\n });\n }\n\n async connect(\n ctx: AdapterContext,\n opts?: {\n timeoutMs?: number;\n partyId?: import('@partylayer/core').PartyId;\n }\n ): Promise<AdapterConnectResult> {\n try {\n // Create connect request\n const state = this.generateState();\n const redirectUri = this.vendorConfig.redirectUri || `${ctx.origin}/callback`;\n const request: import('@partylayer/core').ConnectRequest = {\n appName: ctx.appName,\n origin: ctx.origin,\n network: ctx.network,\n requestedCapabilities: undefined, // Cantor8 doesn't support capability filtering yet\n state,\n redirectUri,\n };\n\n // Create connect URL using vendor module\n const connectUrl = this.vendorModule.createConnectUrl(request, this.vendorConfig);\n\n // Open via transport\n const transportOptions: import('@partylayer/core').TransportOptions = {\n timeoutMs: opts?.timeoutMs || 60000,\n allowedOrigins: [ctx.origin],\n origin: ctx.origin,\n };\n\n const response = await this.transport.openConnectRequest(\n connectUrl,\n request,\n transportOptions\n );\n\n // Check for error\n if (response.error) {\n if (response.error.code === 'USER_REJECTED' || response.error.code === 'CANCELLED') {\n throw new UserRejectedError('User rejected connection');\n }\n throw new Error(response.error.message || 'Connection failed');\n }\n\n if (!response.partyId) {\n throw new Error('No partyId in response');\n }\n\n // Return result\n return {\n partyId: response.partyId,\n session: {\n walletId: this.walletId,\n network: ctx.network,\n createdAt: Date.now(),\n expiresAt: response.expiresAt,\n capabilitiesSnapshot: (response.capabilities || ['connect', 'signMessage']) as CapabilityKey[],\n metadata: {\n sessionToken: response.sessionToken || '',\n },\n },\n capabilities: (response.capabilities || ['connect', 'signMessage']) as CapabilityKey[],\n };\n } catch (err) {\n throw mapUnknownErrorToPartyLayerError(err, {\n walletId: this.walletId,\n phase: 'connect',\n transport: 'deeplink',\n });\n }\n }\n\n disconnect(\n _ctx: AdapterContext,\n _session: import('@partylayer/core').Session\n ): Promise<void> {\n // Cantor8 doesn't have explicit disconnect - session expires naturally\n // Clear any stored session tokens\n if (_session.metadata?.sessionToken) {\n // In production, might call a logout endpoint\n }\n return Promise.resolve();\n }\n\n restore(\n _ctx: AdapterContext,\n persisted: import('@partylayer/core').PersistedSession\n ): Promise<import('@partylayer/core').Session | null> {\n // Check if we have a session token\n const sessionToken = persisted.metadata?.sessionToken;\n if (typeof sessionToken !== 'string') {\n return Promise.resolve(null); // No token to restore\n }\n\n // In production, might validate token with vendor API\n // For now, if token exists and session not expired, restore\n if (persisted.expiresAt && Date.now() >= persisted.expiresAt) {\n return Promise.resolve(null); // Expired\n }\n\n // Return restored session\n return Promise.resolve({\n ...persisted,\n walletId: this.walletId,\n });\n }\n\n async signMessage(\n ctx: AdapterContext,\n session: import('@partylayer/core').Session,\n params: SignMessageParams\n ): Promise<import('@partylayer/core').SignedMessage> {\n try {\n const state = this.generateState();\n const redirectUri = this.vendorConfig.redirectUri || `${ctx.origin}/callback`;\n const request: import('@partylayer/core').SignRequest = {\n message: params.message,\n state,\n redirectUri,\n };\n\n const signUrl = this.vendorModule.createSignUrl(request, this.vendorConfig);\n\n const transportOptions: import('@partylayer/core').TransportOptions = {\n timeoutMs: 60000,\n allowedOrigins: [ctx.origin],\n origin: ctx.origin,\n };\n\n const response = await this.transport.openSignRequest(\n signUrl,\n request,\n transportOptions\n );\n\n if (response.error) {\n if (response.error.code === 'USER_REJECTED') {\n throw new UserRejectedError('User rejected signing');\n }\n throw new Error(response.error.message || 'Signing failed');\n }\n\n if (!response.signature) {\n throw new Error('No signature in response');\n }\n\n return {\n message: params.message,\n signature: toSignature(response.signature),\n partyId: session.partyId,\n };\n } catch (err) {\n throw mapUnknownErrorToPartyLayerError(err, {\n walletId: this.walletId,\n phase: 'signMessage',\n transport: 'deeplink',\n });\n }\n }\n\n async signTransaction(\n ctx: AdapterContext,\n session: import('@partylayer/core').Session,\n params: SignTransactionParams\n ): Promise<import('@partylayer/core').SignedTransaction> {\n try {\n const state = this.generateState();\n const redirectUri = this.vendorConfig.redirectUri || `${ctx.origin}/callback`;\n const request: import('@partylayer/core').SignRequest = {\n transaction: params.tx,\n state,\n redirectUri,\n };\n\n const signUrl = this.vendorModule.createSignUrl(request, this.vendorConfig);\n\n const transportOptions: import('@partylayer/core').TransportOptions = {\n timeoutMs: 60000,\n allowedOrigins: [ctx.origin],\n origin: ctx.origin,\n };\n\n const response = await this.transport.openSignRequest(\n signUrl,\n request,\n transportOptions\n );\n\n if (response.error) {\n if (response.error.code === 'USER_REJECTED') {\n throw new UserRejectedError('User rejected signing');\n }\n throw new Error(response.error.message || 'Signing failed');\n }\n\n // Handle async approval (jobId)\n if (response.jobId && this.vendorModule.pollJobStatus) {\n const statusUrl = this.vendorConfig.statusEndpoint || '';\n const jobStatus = await this.vendorModule.pollJobStatus(\n response.jobId,\n statusUrl,\n 60000\n );\n\n if (jobStatus.status === 'denied') {\n throw new UserRejectedError('Transaction signing denied');\n }\n\n if (jobStatus.status === 'approved' && jobStatus.result?.signature) {\n const signedTx = typeof params.tx === 'object' && params.tx !== null\n ? { ...params.tx as Record<string, unknown>, signature: jobStatus.result.signature }\n : { tx: params.tx, signature: jobStatus.result.signature };\n return {\n signedTx,\n transactionHash: jobStatus.result.transactionHash\n ? toTransactionHash(jobStatus.result.transactionHash)\n : toTransactionHash('pending'),\n partyId: session.partyId,\n };\n }\n\n throw new Error('Job not completed');\n }\n\n if (!response.signature) {\n throw new Error('No signature in response');\n }\n\n const signedTx = typeof params.tx === 'object' && params.tx !== null\n ? { ...params.tx as Record<string, unknown>, signature: response.signature }\n : { tx: params.tx, signature: response.signature };\n return {\n signedTx,\n transactionHash: response.transactionHash\n ? toTransactionHash(response.transactionHash)\n : toTransactionHash('pending'),\n partyId: session.partyId,\n };\n } catch (err) {\n throw mapUnknownErrorToPartyLayerError(err, {\n walletId: this.walletId,\n phase: 'signTransaction',\n transport: 'deeplink',\n });\n }\n }\n\n /**\n * Generate random state nonce\n */\n private generateState(): string {\n const array = new Uint8Array(32);\n crypto.getRandomValues(array);\n return Array.from(array, (byte) => byte.toString(16).padStart(2, '0')).join('');\n }\n}\n"]}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
import { toWalletId, MockTransport, DeepLinkTransport, UserRejectedError, mapUnknownErrorToPartyLayerError, toSignature, toTransactionHash, toPartyId } from '@partylayer/core';
|
|
2
|
+
|
|
3
|
+
// src/cantor8-adapter.ts
|
|
4
|
+
var StubCantor8VendorModule = class {
|
|
5
|
+
createConnectUrl(request, config) {
|
|
6
|
+
if (config.universalLinkBase) {
|
|
7
|
+
const endpoint = config.connectEndpoint || "/connect";
|
|
8
|
+
const url = new URL(endpoint, config.universalLinkBase);
|
|
9
|
+
Object.entries(request).forEach(([key, value]) => {
|
|
10
|
+
if (value !== void 0) {
|
|
11
|
+
url.searchParams.set(key, typeof value === "string" ? value : JSON.stringify(value));
|
|
12
|
+
}
|
|
13
|
+
});
|
|
14
|
+
return url.toString();
|
|
15
|
+
}
|
|
16
|
+
if (config.deepLinkScheme) {
|
|
17
|
+
const params = new URLSearchParams();
|
|
18
|
+
Object.entries(request).forEach(([key, value]) => {
|
|
19
|
+
if (value !== void 0) {
|
|
20
|
+
params.set(key, typeof value === "string" ? value : JSON.stringify(value));
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
return `${config.deepLinkScheme}://connect?${params.toString()}`;
|
|
24
|
+
}
|
|
25
|
+
throw new Error(
|
|
26
|
+
"Cantor8 vendor not configured. Please set deepLinkScheme or universalLinkBase in adapter config."
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
parseConnectCallback(callbackData, expectedState) {
|
|
30
|
+
const data = callbackData;
|
|
31
|
+
if (data.state !== expectedState) {
|
|
32
|
+
throw new Error("State mismatch in callback");
|
|
33
|
+
}
|
|
34
|
+
return {
|
|
35
|
+
state: String(data.state),
|
|
36
|
+
partyId: data.partyId ? toPartyId(String(data.partyId)) : void 0,
|
|
37
|
+
sessionToken: data.sessionToken ? String(data.sessionToken) : void 0,
|
|
38
|
+
expiresAt: data.expiresAt ? Number(data.expiresAt) : void 0,
|
|
39
|
+
capabilities: data.capabilities ? Array.isArray(data.capabilities) ? data.capabilities.map(String) : [] : void 0,
|
|
40
|
+
error: data.error ? {
|
|
41
|
+
code: String(data.error.code || "UNKNOWN"),
|
|
42
|
+
message: String(data.error.message || "Unknown error")
|
|
43
|
+
} : void 0
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
createSignUrl(request, config) {
|
|
47
|
+
if (config.universalLinkBase) {
|
|
48
|
+
const endpoint = config.signEndpoint || "/sign";
|
|
49
|
+
const url = new URL(endpoint, config.universalLinkBase);
|
|
50
|
+
Object.entries(request).forEach(([key, value]) => {
|
|
51
|
+
if (value !== void 0) {
|
|
52
|
+
url.searchParams.set(key, typeof value === "string" ? value : JSON.stringify(value));
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
return url.toString();
|
|
56
|
+
}
|
|
57
|
+
if (config.deepLinkScheme) {
|
|
58
|
+
const params = new URLSearchParams();
|
|
59
|
+
Object.entries(request).forEach(([key, value]) => {
|
|
60
|
+
if (value !== void 0) {
|
|
61
|
+
params.set(key, typeof value === "string" ? value : JSON.stringify(value));
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
return `${config.deepLinkScheme}://sign?${params.toString()}`;
|
|
65
|
+
}
|
|
66
|
+
throw new Error("Cantor8 vendor not configured");
|
|
67
|
+
}
|
|
68
|
+
parseSignCallback(callbackData, expectedState) {
|
|
69
|
+
const data = callbackData;
|
|
70
|
+
if (data.state !== expectedState) {
|
|
71
|
+
throw new Error("State mismatch in callback");
|
|
72
|
+
}
|
|
73
|
+
return {
|
|
74
|
+
state: String(data.state),
|
|
75
|
+
signature: data.signature ? String(data.signature) : void 0,
|
|
76
|
+
transactionHash: data.transactionHash ? String(data.transactionHash) : void 0,
|
|
77
|
+
jobId: data.jobId ? String(data.jobId) : void 0,
|
|
78
|
+
error: data.error ? {
|
|
79
|
+
code: String(data.error.code || "UNKNOWN"),
|
|
80
|
+
message: String(data.error.message || "Unknown error")
|
|
81
|
+
} : void 0
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
// src/cantor8-adapter.ts
|
|
87
|
+
var Cantor8Adapter = class {
|
|
88
|
+
walletId = toWalletId("cantor8");
|
|
89
|
+
name = "Cantor8";
|
|
90
|
+
vendorModule;
|
|
91
|
+
vendorConfig;
|
|
92
|
+
transport;
|
|
93
|
+
constructor(config = {}) {
|
|
94
|
+
this.vendorModule = config.vendorModule || new StubCantor8VendorModule();
|
|
95
|
+
this.vendorConfig = config.vendorConfig || {};
|
|
96
|
+
if (config.useMockTransport || process.env.NODE_ENV === "development") {
|
|
97
|
+
this.transport = new MockTransport();
|
|
98
|
+
} else {
|
|
99
|
+
this.transport = new DeepLinkTransport();
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
getCapabilities() {
|
|
103
|
+
return [
|
|
104
|
+
"connect",
|
|
105
|
+
"disconnect",
|
|
106
|
+
"deeplink",
|
|
107
|
+
"signMessage",
|
|
108
|
+
"signTransaction"
|
|
109
|
+
// restore depends on sessionToken support
|
|
110
|
+
];
|
|
111
|
+
}
|
|
112
|
+
detectInstalled() {
|
|
113
|
+
if (typeof window === "undefined") {
|
|
114
|
+
return Promise.resolve({ installed: false, reason: "Browser environment required" });
|
|
115
|
+
}
|
|
116
|
+
const isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
|
|
117
|
+
return Promise.resolve({
|
|
118
|
+
installed: isMobile,
|
|
119
|
+
reason: isMobile ? void 0 : "Cantor8 is a mobile wallet"
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
async connect(ctx, opts) {
|
|
123
|
+
try {
|
|
124
|
+
const state = this.generateState();
|
|
125
|
+
const redirectUri = this.vendorConfig.redirectUri || `${ctx.origin}/callback`;
|
|
126
|
+
const request = {
|
|
127
|
+
appName: ctx.appName,
|
|
128
|
+
origin: ctx.origin,
|
|
129
|
+
network: ctx.network,
|
|
130
|
+
requestedCapabilities: void 0,
|
|
131
|
+
// Cantor8 doesn't support capability filtering yet
|
|
132
|
+
state,
|
|
133
|
+
redirectUri
|
|
134
|
+
};
|
|
135
|
+
const connectUrl = this.vendorModule.createConnectUrl(request, this.vendorConfig);
|
|
136
|
+
const transportOptions = {
|
|
137
|
+
timeoutMs: opts?.timeoutMs || 6e4,
|
|
138
|
+
allowedOrigins: [ctx.origin],
|
|
139
|
+
origin: ctx.origin
|
|
140
|
+
};
|
|
141
|
+
const response = await this.transport.openConnectRequest(
|
|
142
|
+
connectUrl,
|
|
143
|
+
request,
|
|
144
|
+
transportOptions
|
|
145
|
+
);
|
|
146
|
+
if (response.error) {
|
|
147
|
+
if (response.error.code === "USER_REJECTED" || response.error.code === "CANCELLED") {
|
|
148
|
+
throw new UserRejectedError("User rejected connection");
|
|
149
|
+
}
|
|
150
|
+
throw new Error(response.error.message || "Connection failed");
|
|
151
|
+
}
|
|
152
|
+
if (!response.partyId) {
|
|
153
|
+
throw new Error("No partyId in response");
|
|
154
|
+
}
|
|
155
|
+
return {
|
|
156
|
+
partyId: response.partyId,
|
|
157
|
+
session: {
|
|
158
|
+
walletId: this.walletId,
|
|
159
|
+
network: ctx.network,
|
|
160
|
+
createdAt: Date.now(),
|
|
161
|
+
expiresAt: response.expiresAt,
|
|
162
|
+
capabilitiesSnapshot: response.capabilities || ["connect", "signMessage"],
|
|
163
|
+
metadata: {
|
|
164
|
+
sessionToken: response.sessionToken || ""
|
|
165
|
+
}
|
|
166
|
+
},
|
|
167
|
+
capabilities: response.capabilities || ["connect", "signMessage"]
|
|
168
|
+
};
|
|
169
|
+
} catch (err) {
|
|
170
|
+
throw mapUnknownErrorToPartyLayerError(err, {
|
|
171
|
+
walletId: this.walletId,
|
|
172
|
+
phase: "connect",
|
|
173
|
+
transport: "deeplink"
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
disconnect(_ctx, _session) {
|
|
178
|
+
if (_session.metadata?.sessionToken) ;
|
|
179
|
+
return Promise.resolve();
|
|
180
|
+
}
|
|
181
|
+
restore(_ctx, persisted) {
|
|
182
|
+
const sessionToken = persisted.metadata?.sessionToken;
|
|
183
|
+
if (typeof sessionToken !== "string") {
|
|
184
|
+
return Promise.resolve(null);
|
|
185
|
+
}
|
|
186
|
+
if (persisted.expiresAt && Date.now() >= persisted.expiresAt) {
|
|
187
|
+
return Promise.resolve(null);
|
|
188
|
+
}
|
|
189
|
+
return Promise.resolve({
|
|
190
|
+
...persisted,
|
|
191
|
+
walletId: this.walletId
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
async signMessage(ctx, session, params) {
|
|
195
|
+
try {
|
|
196
|
+
const state = this.generateState();
|
|
197
|
+
const redirectUri = this.vendorConfig.redirectUri || `${ctx.origin}/callback`;
|
|
198
|
+
const request = {
|
|
199
|
+
message: params.message,
|
|
200
|
+
state,
|
|
201
|
+
redirectUri
|
|
202
|
+
};
|
|
203
|
+
const signUrl = this.vendorModule.createSignUrl(request, this.vendorConfig);
|
|
204
|
+
const transportOptions = {
|
|
205
|
+
timeoutMs: 6e4,
|
|
206
|
+
allowedOrigins: [ctx.origin],
|
|
207
|
+
origin: ctx.origin
|
|
208
|
+
};
|
|
209
|
+
const response = await this.transport.openSignRequest(
|
|
210
|
+
signUrl,
|
|
211
|
+
request,
|
|
212
|
+
transportOptions
|
|
213
|
+
);
|
|
214
|
+
if (response.error) {
|
|
215
|
+
if (response.error.code === "USER_REJECTED") {
|
|
216
|
+
throw new UserRejectedError("User rejected signing");
|
|
217
|
+
}
|
|
218
|
+
throw new Error(response.error.message || "Signing failed");
|
|
219
|
+
}
|
|
220
|
+
if (!response.signature) {
|
|
221
|
+
throw new Error("No signature in response");
|
|
222
|
+
}
|
|
223
|
+
return {
|
|
224
|
+
message: params.message,
|
|
225
|
+
signature: toSignature(response.signature),
|
|
226
|
+
partyId: session.partyId
|
|
227
|
+
};
|
|
228
|
+
} catch (err) {
|
|
229
|
+
throw mapUnknownErrorToPartyLayerError(err, {
|
|
230
|
+
walletId: this.walletId,
|
|
231
|
+
phase: "signMessage",
|
|
232
|
+
transport: "deeplink"
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
async signTransaction(ctx, session, params) {
|
|
237
|
+
try {
|
|
238
|
+
const state = this.generateState();
|
|
239
|
+
const redirectUri = this.vendorConfig.redirectUri || `${ctx.origin}/callback`;
|
|
240
|
+
const request = {
|
|
241
|
+
transaction: params.tx,
|
|
242
|
+
state,
|
|
243
|
+
redirectUri
|
|
244
|
+
};
|
|
245
|
+
const signUrl = this.vendorModule.createSignUrl(request, this.vendorConfig);
|
|
246
|
+
const transportOptions = {
|
|
247
|
+
timeoutMs: 6e4,
|
|
248
|
+
allowedOrigins: [ctx.origin],
|
|
249
|
+
origin: ctx.origin
|
|
250
|
+
};
|
|
251
|
+
const response = await this.transport.openSignRequest(
|
|
252
|
+
signUrl,
|
|
253
|
+
request,
|
|
254
|
+
transportOptions
|
|
255
|
+
);
|
|
256
|
+
if (response.error) {
|
|
257
|
+
if (response.error.code === "USER_REJECTED") {
|
|
258
|
+
throw new UserRejectedError("User rejected signing");
|
|
259
|
+
}
|
|
260
|
+
throw new Error(response.error.message || "Signing failed");
|
|
261
|
+
}
|
|
262
|
+
if (response.jobId && this.vendorModule.pollJobStatus) {
|
|
263
|
+
const statusUrl = this.vendorConfig.statusEndpoint || "";
|
|
264
|
+
const jobStatus = await this.vendorModule.pollJobStatus(
|
|
265
|
+
response.jobId,
|
|
266
|
+
statusUrl,
|
|
267
|
+
6e4
|
|
268
|
+
);
|
|
269
|
+
if (jobStatus.status === "denied") {
|
|
270
|
+
throw new UserRejectedError("Transaction signing denied");
|
|
271
|
+
}
|
|
272
|
+
if (jobStatus.status === "approved" && jobStatus.result?.signature) {
|
|
273
|
+
const signedTx2 = typeof params.tx === "object" && params.tx !== null ? { ...params.tx, signature: jobStatus.result.signature } : { tx: params.tx, signature: jobStatus.result.signature };
|
|
274
|
+
return {
|
|
275
|
+
signedTx: signedTx2,
|
|
276
|
+
transactionHash: jobStatus.result.transactionHash ? toTransactionHash(jobStatus.result.transactionHash) : toTransactionHash("pending"),
|
|
277
|
+
partyId: session.partyId
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
throw new Error("Job not completed");
|
|
281
|
+
}
|
|
282
|
+
if (!response.signature) {
|
|
283
|
+
throw new Error("No signature in response");
|
|
284
|
+
}
|
|
285
|
+
const signedTx = typeof params.tx === "object" && params.tx !== null ? { ...params.tx, signature: response.signature } : { tx: params.tx, signature: response.signature };
|
|
286
|
+
return {
|
|
287
|
+
signedTx,
|
|
288
|
+
transactionHash: response.transactionHash ? toTransactionHash(response.transactionHash) : toTransactionHash("pending"),
|
|
289
|
+
partyId: session.partyId
|
|
290
|
+
};
|
|
291
|
+
} catch (err) {
|
|
292
|
+
throw mapUnknownErrorToPartyLayerError(err, {
|
|
293
|
+
walletId: this.walletId,
|
|
294
|
+
phase: "signTransaction",
|
|
295
|
+
transport: "deeplink"
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Generate random state nonce
|
|
301
|
+
*/
|
|
302
|
+
generateState() {
|
|
303
|
+
const array = new Uint8Array(32);
|
|
304
|
+
crypto.getRandomValues(array);
|
|
305
|
+
return Array.from(array, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
306
|
+
}
|
|
307
|
+
};
|
|
308
|
+
|
|
309
|
+
export { Cantor8Adapter };
|
|
310
|
+
//# sourceMappingURL=index.mjs.map
|
|
311
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/vendor.ts","../src/cantor8-adapter.ts"],"names":["signedTx"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * Cantor8 Vendor Integration Module\n * \n * This module abstracts vendor-specific endpoints and can be swapped\n * without breaking the adapter API.\n * \n * References:\n * - Cantor8 ecosystem: https://www.canton.network/ecosystem/cantor8\n * - Cantor8 site: https://cantor8.tech/about\n */\n\nimport type {\n ConnectRequest,\n ConnectResponse,\n SignRequest,\n SignResponse,\n JobStatus,\n} from '@partylayer/core';\nimport { toPartyId } from '@partylayer/core';\n\n/**\n * Vendor configuration\n */\nexport interface Cantor8VendorConfig {\n /** Deep link scheme (e.g., \"cantor8\") */\n deepLinkScheme?: string;\n /** Universal link base URL (e.g., \"https://app.cantor8.tech\") */\n universalLinkBase?: string;\n /** Connect endpoint path */\n connectEndpoint?: string;\n /** Sign endpoint path */\n signEndpoint?: string;\n /** Job status endpoint path (for async approvals) */\n statusEndpoint?: string;\n /** Redirect URI for callbacks */\n redirectUri?: string;\n}\n\n/**\n * Vendor module interface\n * \n * Implementations can be swapped without changing adapter code.\n */\nexport interface Cantor8VendorModule {\n /**\n * Create connect URL\n */\n createConnectUrl(request: ConnectRequest, config: Cantor8VendorConfig): string;\n\n /**\n * Parse connect callback\n */\n parseConnectCallback(\n callbackData: unknown,\n expectedState: string\n ): ConnectResponse;\n\n /**\n * Create sign URL\n */\n createSignUrl(request: SignRequest, config: Cantor8VendorConfig): string;\n\n /**\n * Parse sign callback\n */\n parseSignCallback(\n callbackData: unknown,\n expectedState: string\n ): SignResponse;\n\n /**\n * Poll job status (optional, for async approvals)\n */\n pollJobStatus?(\n jobId: string,\n statusUrl: string,\n timeoutMs: number\n ): Promise<JobStatus>;\n}\n\n/**\n * Default/stub vendor module\n * \n * This implementation provides a structured interface but throws\n * NotConfiguredError with clear instructions when vendor endpoints\n * are not configured.\n */\nexport class StubCantor8VendorModule implements Cantor8VendorModule {\n createConnectUrl(request: ConnectRequest, config: Cantor8VendorConfig): string {\n // Prefer universal link if configured\n if (config.universalLinkBase) {\n const endpoint = config.connectEndpoint || '/connect';\n const url = new URL(endpoint, config.universalLinkBase);\n Object.entries(request).forEach(([key, value]) => {\n if (value !== undefined) {\n url.searchParams.set(key, typeof value === 'string' ? value : JSON.stringify(value));\n }\n });\n return url.toString();\n }\n\n // Fallback to deep link scheme\n if (config.deepLinkScheme) {\n const params = new URLSearchParams();\n Object.entries(request).forEach(([key, value]) => {\n if (value !== undefined) {\n params.set(key, typeof value === 'string' ? value : JSON.stringify(value));\n }\n });\n return `${config.deepLinkScheme}://connect?${params.toString()}`;\n }\n\n throw new Error(\n 'Cantor8 vendor not configured. Please set deepLinkScheme or universalLinkBase in adapter config.'\n );\n }\n\n parseConnectCallback(\n callbackData: unknown,\n expectedState: string\n ): ConnectResponse {\n // Parse callback data (could be URL params, postMessage, etc.)\n const data = callbackData as Record<string, unknown>;\n\n // Validate state\n if (data.state !== expectedState) {\n throw new Error('State mismatch in callback');\n }\n\n // Return response\n return {\n state: String(data.state),\n partyId: data.partyId ? toPartyId(String(data.partyId)) : undefined,\n sessionToken: data.sessionToken ? String(data.sessionToken) : undefined,\n expiresAt: data.expiresAt ? Number(data.expiresAt) : undefined,\n capabilities: data.capabilities\n ? (Array.isArray(data.capabilities) ? data.capabilities.map(String) : [])\n : undefined,\n error: data.error\n ? {\n code: String((data.error as Record<string, unknown>).code || 'UNKNOWN'),\n message: String((data.error as Record<string, unknown>).message || 'Unknown error'),\n }\n : undefined,\n };\n }\n\n createSignUrl(request: SignRequest, config: Cantor8VendorConfig): string {\n if (config.universalLinkBase) {\n const endpoint = config.signEndpoint || '/sign';\n const url = new URL(endpoint, config.universalLinkBase);\n Object.entries(request).forEach(([key, value]) => {\n if (value !== undefined) {\n url.searchParams.set(key, typeof value === 'string' ? value : JSON.stringify(value));\n }\n });\n return url.toString();\n }\n\n if (config.deepLinkScheme) {\n const params = new URLSearchParams();\n Object.entries(request).forEach(([key, value]) => {\n if (value !== undefined) {\n params.set(key, typeof value === 'string' ? value : JSON.stringify(value));\n }\n });\n return `${config.deepLinkScheme}://sign?${params.toString()}`;\n }\n\n throw new Error('Cantor8 vendor not configured');\n }\n\n parseSignCallback(\n callbackData: unknown,\n expectedState: string\n ): SignResponse {\n const data = callbackData as Record<string, unknown>;\n\n if (data.state !== expectedState) {\n throw new Error('State mismatch in callback');\n }\n\n return {\n state: String(data.state),\n signature: data.signature ? String(data.signature) : undefined,\n transactionHash: data.transactionHash ? String(data.transactionHash) : undefined,\n jobId: data.jobId ? String(data.jobId) : undefined,\n error: data.error\n ? {\n code: String((data.error as Record<string, unknown>).code || 'UNKNOWN'),\n message: String((data.error as Record<string, unknown>).message || 'Unknown error'),\n }\n : undefined,\n };\n }\n}\n","/**\n * Cantor8 (C8) Wallet Adapter\n * \n * Implements WalletAdapter interface for Cantor8 wallet using deep link transport.\n * \n * References:\n * - Cantor8 ecosystem: https://www.canton.network/ecosystem/cantor8\n * - Cantor8 site: https://cantor8.tech/about\n * - Wallet Integration Guide: https://docs.digitalasset.com/integrate/devnet/index.html\n */\n\nimport type {\n WalletAdapter,\n AdapterContext,\n AdapterDetectResult,\n AdapterConnectResult,\n SignMessageParams,\n SignTransactionParams,\n} from '@partylayer/core';\nimport {\n toWalletId,\n toSignature,\n toTransactionHash,\n UserRejectedError,\n mapUnknownErrorToPartyLayerError,\n type CapabilityKey,\n} from '@partylayer/core';\nimport { DeepLinkTransport, MockTransport } from '@partylayer/core';\nimport type {\n Cantor8VendorModule,\n Cantor8VendorConfig,\n} from './vendor';\nimport {\n StubCantor8VendorModule,\n} from './vendor';\n\n/**\n * Cantor8 adapter configuration\n */\nexport interface Cantor8AdapterConfig {\n /** Vendor module (defaults to stub) */\n vendorModule?: Cantor8VendorModule;\n /** Vendor configuration */\n vendorConfig?: Cantor8VendorConfig;\n /** Use mock transport in development */\n useMockTransport?: boolean;\n}\n\n/**\n * Cantor8 Wallet Adapter\n */\nexport class Cantor8Adapter implements WalletAdapter {\n readonly walletId = toWalletId('cantor8');\n readonly name = 'Cantor8';\n\n private vendorModule: Cantor8VendorModule;\n private vendorConfig: Cantor8VendorConfig;\n private transport: DeepLinkTransport | MockTransport;\n\n constructor(config: Cantor8AdapterConfig = {}) {\n this.vendorModule = config.vendorModule || new StubCantor8VendorModule();\n this.vendorConfig = config.vendorConfig || {};\n \n // Use mock transport in development if configured\n if (config.useMockTransport || process.env.NODE_ENV === 'development') {\n this.transport = new MockTransport();\n } else {\n this.transport = new DeepLinkTransport();\n }\n }\n\n getCapabilities(): CapabilityKey[] {\n return [\n 'connect',\n 'disconnect',\n 'deeplink',\n 'signMessage',\n 'signTransaction',\n // restore depends on sessionToken support\n ];\n }\n\n detectInstalled(): Promise<AdapterDetectResult> {\n // Cantor8 is a mobile wallet - detection is not straightforward\n // We can check for deep link support or user agent hints\n if (typeof window === 'undefined') {\n return Promise.resolve({ installed: false, reason: 'Browser environment required' });\n }\n\n // Check if device supports deep links (mobile)\n const isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);\n \n // For now, assume installed if mobile device\n // In production, might check for specific user agent or other hints\n return Promise.resolve({\n installed: isMobile,\n reason: isMobile ? undefined : 'Cantor8 is a mobile wallet',\n });\n }\n\n async connect(\n ctx: AdapterContext,\n opts?: {\n timeoutMs?: number;\n partyId?: import('@partylayer/core').PartyId;\n }\n ): Promise<AdapterConnectResult> {\n try {\n // Create connect request\n const state = this.generateState();\n const redirectUri = this.vendorConfig.redirectUri || `${ctx.origin}/callback`;\n const request: import('@partylayer/core').ConnectRequest = {\n appName: ctx.appName,\n origin: ctx.origin,\n network: ctx.network,\n requestedCapabilities: undefined, // Cantor8 doesn't support capability filtering yet\n state,\n redirectUri,\n };\n\n // Create connect URL using vendor module\n const connectUrl = this.vendorModule.createConnectUrl(request, this.vendorConfig);\n\n // Open via transport\n const transportOptions: import('@partylayer/core').TransportOptions = {\n timeoutMs: opts?.timeoutMs || 60000,\n allowedOrigins: [ctx.origin],\n origin: ctx.origin,\n };\n\n const response = await this.transport.openConnectRequest(\n connectUrl,\n request,\n transportOptions\n );\n\n // Check for error\n if (response.error) {\n if (response.error.code === 'USER_REJECTED' || response.error.code === 'CANCELLED') {\n throw new UserRejectedError('User rejected connection');\n }\n throw new Error(response.error.message || 'Connection failed');\n }\n\n if (!response.partyId) {\n throw new Error('No partyId in response');\n }\n\n // Return result\n return {\n partyId: response.partyId,\n session: {\n walletId: this.walletId,\n network: ctx.network,\n createdAt: Date.now(),\n expiresAt: response.expiresAt,\n capabilitiesSnapshot: (response.capabilities || ['connect', 'signMessage']) as CapabilityKey[],\n metadata: {\n sessionToken: response.sessionToken || '',\n },\n },\n capabilities: (response.capabilities || ['connect', 'signMessage']) as CapabilityKey[],\n };\n } catch (err) {\n throw mapUnknownErrorToPartyLayerError(err, {\n walletId: this.walletId,\n phase: 'connect',\n transport: 'deeplink',\n });\n }\n }\n\n disconnect(\n _ctx: AdapterContext,\n _session: import('@partylayer/core').Session\n ): Promise<void> {\n // Cantor8 doesn't have explicit disconnect - session expires naturally\n // Clear any stored session tokens\n if (_session.metadata?.sessionToken) {\n // In production, might call a logout endpoint\n }\n return Promise.resolve();\n }\n\n restore(\n _ctx: AdapterContext,\n persisted: import('@partylayer/core').PersistedSession\n ): Promise<import('@partylayer/core').Session | null> {\n // Check if we have a session token\n const sessionToken = persisted.metadata?.sessionToken;\n if (typeof sessionToken !== 'string') {\n return Promise.resolve(null); // No token to restore\n }\n\n // In production, might validate token with vendor API\n // For now, if token exists and session not expired, restore\n if (persisted.expiresAt && Date.now() >= persisted.expiresAt) {\n return Promise.resolve(null); // Expired\n }\n\n // Return restored session\n return Promise.resolve({\n ...persisted,\n walletId: this.walletId,\n });\n }\n\n async signMessage(\n ctx: AdapterContext,\n session: import('@partylayer/core').Session,\n params: SignMessageParams\n ): Promise<import('@partylayer/core').SignedMessage> {\n try {\n const state = this.generateState();\n const redirectUri = this.vendorConfig.redirectUri || `${ctx.origin}/callback`;\n const request: import('@partylayer/core').SignRequest = {\n message: params.message,\n state,\n redirectUri,\n };\n\n const signUrl = this.vendorModule.createSignUrl(request, this.vendorConfig);\n\n const transportOptions: import('@partylayer/core').TransportOptions = {\n timeoutMs: 60000,\n allowedOrigins: [ctx.origin],\n origin: ctx.origin,\n };\n\n const response = await this.transport.openSignRequest(\n signUrl,\n request,\n transportOptions\n );\n\n if (response.error) {\n if (response.error.code === 'USER_REJECTED') {\n throw new UserRejectedError('User rejected signing');\n }\n throw new Error(response.error.message || 'Signing failed');\n }\n\n if (!response.signature) {\n throw new Error('No signature in response');\n }\n\n return {\n message: params.message,\n signature: toSignature(response.signature),\n partyId: session.partyId,\n };\n } catch (err) {\n throw mapUnknownErrorToPartyLayerError(err, {\n walletId: this.walletId,\n phase: 'signMessage',\n transport: 'deeplink',\n });\n }\n }\n\n async signTransaction(\n ctx: AdapterContext,\n session: import('@partylayer/core').Session,\n params: SignTransactionParams\n ): Promise<import('@partylayer/core').SignedTransaction> {\n try {\n const state = this.generateState();\n const redirectUri = this.vendorConfig.redirectUri || `${ctx.origin}/callback`;\n const request: import('@partylayer/core').SignRequest = {\n transaction: params.tx,\n state,\n redirectUri,\n };\n\n const signUrl = this.vendorModule.createSignUrl(request, this.vendorConfig);\n\n const transportOptions: import('@partylayer/core').TransportOptions = {\n timeoutMs: 60000,\n allowedOrigins: [ctx.origin],\n origin: ctx.origin,\n };\n\n const response = await this.transport.openSignRequest(\n signUrl,\n request,\n transportOptions\n );\n\n if (response.error) {\n if (response.error.code === 'USER_REJECTED') {\n throw new UserRejectedError('User rejected signing');\n }\n throw new Error(response.error.message || 'Signing failed');\n }\n\n // Handle async approval (jobId)\n if (response.jobId && this.vendorModule.pollJobStatus) {\n const statusUrl = this.vendorConfig.statusEndpoint || '';\n const jobStatus = await this.vendorModule.pollJobStatus(\n response.jobId,\n statusUrl,\n 60000\n );\n\n if (jobStatus.status === 'denied') {\n throw new UserRejectedError('Transaction signing denied');\n }\n\n if (jobStatus.status === 'approved' && jobStatus.result?.signature) {\n const signedTx = typeof params.tx === 'object' && params.tx !== null\n ? { ...params.tx as Record<string, unknown>, signature: jobStatus.result.signature }\n : { tx: params.tx, signature: jobStatus.result.signature };\n return {\n signedTx,\n transactionHash: jobStatus.result.transactionHash\n ? toTransactionHash(jobStatus.result.transactionHash)\n : toTransactionHash('pending'),\n partyId: session.partyId,\n };\n }\n\n throw new Error('Job not completed');\n }\n\n if (!response.signature) {\n throw new Error('No signature in response');\n }\n\n const signedTx = typeof params.tx === 'object' && params.tx !== null\n ? { ...params.tx as Record<string, unknown>, signature: response.signature }\n : { tx: params.tx, signature: response.signature };\n return {\n signedTx,\n transactionHash: response.transactionHash\n ? toTransactionHash(response.transactionHash)\n : toTransactionHash('pending'),\n partyId: session.partyId,\n };\n } catch (err) {\n throw mapUnknownErrorToPartyLayerError(err, {\n walletId: this.walletId,\n phase: 'signTransaction',\n transport: 'deeplink',\n });\n }\n }\n\n /**\n * Generate random state nonce\n */\n private generateState(): string {\n const array = new Uint8Array(32);\n crypto.getRandomValues(array);\n return Array.from(array, (byte) => byte.toString(16).padStart(2, '0')).join('');\n }\n}\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@partylayer/adapter-cantor8",
|
|
3
|
+
"version": "0.2.2",
|
|
4
|
+
"description": "Cantor8 (C8) Wallet adapter for PartyLayer",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"module": "./dist/index.mjs",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.mjs",
|
|
12
|
+
"require": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist"
|
|
17
|
+
],
|
|
18
|
+
"keywords": [
|
|
19
|
+
"canton",
|
|
20
|
+
"wallet",
|
|
21
|
+
"cantor8"
|
|
22
|
+
],
|
|
23
|
+
"author": "PartyLayer Contributors",
|
|
24
|
+
"license": "MIT",
|
|
25
|
+
"repository": {
|
|
26
|
+
"type": "git",
|
|
27
|
+
"url": "https://github.com/cayvox/PartyLayer.git",
|
|
28
|
+
"directory": "packages/adapters/cantor8"
|
|
29
|
+
},
|
|
30
|
+
"homepage": "https://github.com/cayvox/PartyLayer#readme",
|
|
31
|
+
"bugs": {
|
|
32
|
+
"url": "https://github.com/cayvox/PartyLayer/issues"
|
|
33
|
+
},
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"@partylayer/core": "0.2.2"
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@types/node": "^20.11.0",
|
|
39
|
+
"typescript": "^5.3.3"
|
|
40
|
+
},
|
|
41
|
+
"scripts": {
|
|
42
|
+
"build": "tsup",
|
|
43
|
+
"clean": "rm -rf dist",
|
|
44
|
+
"lint": "eslint src --ext .ts",
|
|
45
|
+
"typecheck": "tsc --noEmit"
|
|
46
|
+
}
|
|
47
|
+
}
|