@ckb-ccc/joy-id 0.0.5-alpha.7 → 0.0.6-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/btc/index.d.ts +46 -1
- package/dist/btc/index.d.ts.map +1 -1
- package/dist/btc/index.js +46 -3
- package/dist/ckb/index.d.ts +95 -2
- package/dist/ckb/index.d.ts.map +1 -1
- package/dist/ckb/index.js +98 -8
- package/dist/common/index.d.ts +13 -0
- package/dist/common/index.d.ts.map +1 -1
- package/dist/common/index.js +9 -0
- package/dist/connectionsStorage/index.d.ts +58 -0
- package/dist/connectionsStorage/index.d.ts.map +1 -1
- package/dist/connectionsStorage/index.js +30 -0
- package/dist/evm/index.d.ts +51 -1
- package/dist/evm/index.d.ts.map +1 -1
- package/dist/evm/index.js +52 -4
- package/dist/nostr/index.d.ts +51 -0
- package/dist/nostr/index.d.ts.map +1 -0
- package/dist/nostr/index.js +106 -0
- package/dist/signerFactory/index.d.ts +9 -0
- package/dist/signerFactory/index.d.ts.map +1 -1
- package/dist/signerFactory/index.js +20 -2
- package/dist.commonjs/btc/index.d.ts +46 -1
- package/dist.commonjs/btc/index.d.ts.map +1 -1
- package/dist.commonjs/btc/index.js +46 -3
- package/dist.commonjs/ckb/index.d.ts +95 -2
- package/dist.commonjs/ckb/index.d.ts.map +1 -1
- package/dist.commonjs/ckb/index.js +98 -8
- package/dist.commonjs/common/index.d.ts +13 -0
- package/dist.commonjs/common/index.d.ts.map +1 -1
- package/dist.commonjs/common/index.js +9 -0
- package/dist.commonjs/connectionsStorage/index.d.ts +58 -0
- package/dist.commonjs/connectionsStorage/index.d.ts.map +1 -1
- package/dist.commonjs/connectionsStorage/index.js +30 -0
- package/dist.commonjs/evm/index.d.ts +51 -1
- package/dist.commonjs/evm/index.d.ts.map +1 -1
- package/dist.commonjs/evm/index.js +52 -4
- package/dist.commonjs/nostr/index.d.ts +51 -0
- package/dist.commonjs/nostr/index.d.ts.map +1 -0
- package/dist.commonjs/nostr/index.js +110 -0
- package/dist.commonjs/signerFactory/index.d.ts +9 -0
- package/dist.commonjs/signerFactory/index.d.ts.map +1 -1
- package/dist.commonjs/signerFactory/index.js +20 -2
- package/package.json +3 -3
- package/src/btc/index.ts +47 -12
- package/src/ckb/index.ts +104 -19
- package/src/common/index.ts +13 -0
- package/src/connectionsStorage/index.ts +64 -2
- package/src/evm/index.ts +56 -15
- package/src/nostr/index.ts +135 -0
- package/src/signerFactory/index.ts +25 -2
package/src/ckb/index.ts
CHANGED
|
@@ -8,17 +8,36 @@ import {
|
|
|
8
8
|
ConnectionsRepoLocalStorage,
|
|
9
9
|
} from "../connectionsStorage";
|
|
10
10
|
|
|
11
|
+
/**
|
|
12
|
+
* Class representing a CKB signer that extends Signer from @ckb-ccc/core.
|
|
13
|
+
* @class
|
|
14
|
+
* @extends {ccc.Signer}
|
|
15
|
+
*/
|
|
11
16
|
export class CkbSigner extends ccc.Signer {
|
|
17
|
+
/**
|
|
18
|
+
* Gets the signer type.
|
|
19
|
+
* @returns {ccc.SignerType} The type of the signer.
|
|
20
|
+
*/
|
|
12
21
|
get type(): ccc.SignerType {
|
|
13
22
|
return ccc.SignerType.CKB;
|
|
14
23
|
}
|
|
15
24
|
|
|
25
|
+
/**
|
|
26
|
+
* Gets the sign type.
|
|
27
|
+
* @returns {ccc.SignerSignType} The sign type.
|
|
28
|
+
*/
|
|
16
29
|
get signType(): ccc.SignerSignType {
|
|
17
30
|
return ccc.SignerSignType.JoyId;
|
|
18
31
|
}
|
|
19
32
|
|
|
20
33
|
private connection?: Connection;
|
|
21
34
|
|
|
35
|
+
/**
|
|
36
|
+
* Ensures that the signer is connected and returns the connection.
|
|
37
|
+
* @private
|
|
38
|
+
* @throws Will throw an error if not connected.
|
|
39
|
+
* @returns {Promise<Connection>} A promise that resolves to the current connection.
|
|
40
|
+
*/
|
|
22
41
|
private async assertConnection(): Promise<Connection> {
|
|
23
42
|
if (!(await this.isConnected()) || !this.connection) {
|
|
24
43
|
throw new Error("Not connected");
|
|
@@ -27,6 +46,15 @@ export class CkbSigner extends ccc.Signer {
|
|
|
27
46
|
return this.connection;
|
|
28
47
|
}
|
|
29
48
|
|
|
49
|
+
/**
|
|
50
|
+
* Creates an instance of CkbSigner.
|
|
51
|
+
* @param {ccc.Client} client - The client instance.
|
|
52
|
+
* @param {string} name - The name of the signer.
|
|
53
|
+
* @param {string} icon - The icon URL of the signer.
|
|
54
|
+
* @param {string} [_appUri] - The application URI.
|
|
55
|
+
* @param {string} [_aggregatorUri] - The aggregator URI.
|
|
56
|
+
* @param {ConnectionsRepo} [connectionsRepo=new ConnectionsRepoLocalStorage()] - The connections repository.
|
|
57
|
+
*/
|
|
30
58
|
constructor(
|
|
31
59
|
client: ccc.Client,
|
|
32
60
|
private readonly name: string,
|
|
@@ -38,17 +66,11 @@ export class CkbSigner extends ccc.Signer {
|
|
|
38
66
|
super(client);
|
|
39
67
|
}
|
|
40
68
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
this._appUri,
|
|
47
|
-
this._aggregatorUri,
|
|
48
|
-
this.connectionsRepo,
|
|
49
|
-
);
|
|
50
|
-
}
|
|
51
|
-
|
|
69
|
+
/**
|
|
70
|
+
* Gets the configuration for JoyID.
|
|
71
|
+
* @private
|
|
72
|
+
* @returns {object} The configuration object.
|
|
73
|
+
*/
|
|
52
74
|
private getConfig() {
|
|
53
75
|
return {
|
|
54
76
|
redirectURL: location.href,
|
|
@@ -61,6 +83,11 @@ export class CkbSigner extends ccc.Signer {
|
|
|
61
83
|
};
|
|
62
84
|
}
|
|
63
85
|
|
|
86
|
+
/**
|
|
87
|
+
* Gets the aggregator URI.
|
|
88
|
+
* @private
|
|
89
|
+
* @returns {string} The aggregator URI.
|
|
90
|
+
*/
|
|
64
91
|
private getAggregatorUri(): string {
|
|
65
92
|
if (this._aggregatorUri) {
|
|
66
93
|
return this._aggregatorUri;
|
|
@@ -71,6 +98,10 @@ export class CkbSigner extends ccc.Signer {
|
|
|
71
98
|
: "https://cota.nervina.dev/aggregator";
|
|
72
99
|
}
|
|
73
100
|
|
|
101
|
+
/**
|
|
102
|
+
* Connects to the provider by requesting authentication.
|
|
103
|
+
* @returns {Promise<void>} A promise that resolves when the connection is established.
|
|
104
|
+
*/
|
|
74
105
|
async connect(): Promise<void> {
|
|
75
106
|
const config = this.getConfig();
|
|
76
107
|
|
|
@@ -87,11 +118,10 @@ export class CkbSigner extends ccc.Signer {
|
|
|
87
118
|
await this.saveConnection();
|
|
88
119
|
}
|
|
89
120
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
121
|
+
/**
|
|
122
|
+
* Checks if the signer is connected.
|
|
123
|
+
* @returns {Promise<boolean>} A promise that resolves to true if connected, false otherwise.
|
|
124
|
+
*/
|
|
95
125
|
async isConnected(): Promise<boolean> {
|
|
96
126
|
if (this.connection) {
|
|
97
127
|
return true;
|
|
@@ -100,10 +130,18 @@ export class CkbSigner extends ccc.Signer {
|
|
|
100
130
|
return this.connection !== undefined;
|
|
101
131
|
}
|
|
102
132
|
|
|
133
|
+
/**
|
|
134
|
+
* Gets the internal address.
|
|
135
|
+
* @returns {Promise<string>} A promise that resolves to the internal address.
|
|
136
|
+
*/
|
|
103
137
|
async getInternalAddress(): Promise<string> {
|
|
104
138
|
return (await this.assertConnection()).address;
|
|
105
139
|
}
|
|
106
140
|
|
|
141
|
+
/**
|
|
142
|
+
* Gets the identity of the signer.
|
|
143
|
+
* @returns {Promise<string>} A promise that resolves to the identity.
|
|
144
|
+
*/
|
|
107
145
|
async getIdentity(): Promise<string> {
|
|
108
146
|
const connection = await this.assertConnection();
|
|
109
147
|
return JSON.stringify({
|
|
@@ -112,6 +150,10 @@ export class CkbSigner extends ccc.Signer {
|
|
|
112
150
|
});
|
|
113
151
|
}
|
|
114
152
|
|
|
153
|
+
/**
|
|
154
|
+
* Gets the address object.
|
|
155
|
+
* @returns {Promise<ccc.Address>} A promise that resolves to the address object.
|
|
156
|
+
*/
|
|
115
157
|
async getAddressObj(): Promise<ccc.Address> {
|
|
116
158
|
return await ccc.Address.fromString(
|
|
117
159
|
await this.getInternalAddress(),
|
|
@@ -119,10 +161,19 @@ export class CkbSigner extends ccc.Signer {
|
|
|
119
161
|
);
|
|
120
162
|
}
|
|
121
163
|
|
|
164
|
+
/**
|
|
165
|
+
* Gets the address objects.
|
|
166
|
+
* @returns {Promise<ccc.Address[]>} A promise that resolves to an array of address objects.
|
|
167
|
+
*/
|
|
122
168
|
async getAddressObjs(): Promise<ccc.Address[]> {
|
|
123
169
|
return [await this.getAddressObj()];
|
|
124
170
|
}
|
|
125
171
|
|
|
172
|
+
/**
|
|
173
|
+
* Prepares a transaction.
|
|
174
|
+
* @param {ccc.TransactionLike} txLike - The transaction-like object.
|
|
175
|
+
* @returns {Promise<ccc.Transaction>} A promise that resolves to the prepared transaction.
|
|
176
|
+
*/
|
|
126
177
|
async prepareTransaction(
|
|
127
178
|
txLike: ccc.TransactionLike,
|
|
128
179
|
): Promise<ccc.Transaction> {
|
|
@@ -138,9 +189,19 @@ export class CkbSigner extends ccc.Signer {
|
|
|
138
189
|
const witness = tx.getWitnessArgsAt(position) ?? ccc.WitnessArgs.from({});
|
|
139
190
|
witness.lock = "0x";
|
|
140
191
|
await this.prepareTransactionForSubKey(tx, witness);
|
|
141
|
-
|
|
192
|
+
tx.setWitnessArgsAt(position, witness);
|
|
193
|
+
|
|
194
|
+
return tx;
|
|
142
195
|
}
|
|
143
196
|
|
|
197
|
+
/**
|
|
198
|
+
* Prepares a transaction for a sub key.
|
|
199
|
+
* @private
|
|
200
|
+
* @param {ccc.Transaction} tx - The transaction object.
|
|
201
|
+
* @param {ccc.WitnessArgs} witness - The witness arguments.
|
|
202
|
+
* @returns {Promise<void>}
|
|
203
|
+
* @throws Will throw an error if no COTA cells are found for the sub key wallet.
|
|
204
|
+
*/
|
|
144
205
|
private async prepareTransactionForSubKey(
|
|
145
206
|
tx: ccc.Transaction,
|
|
146
207
|
witness: ccc.WitnessArgs,
|
|
@@ -180,6 +241,11 @@ export class CkbSigner extends ccc.Signer {
|
|
|
180
241
|
tx.cellDeps.unshift(...cotaDeps);
|
|
181
242
|
}
|
|
182
243
|
|
|
244
|
+
/**
|
|
245
|
+
* Signs a transaction.
|
|
246
|
+
* @param {ccc.TransactionLike} txLike - The transaction-like object.
|
|
247
|
+
* @returns {Promise<ccc.Transaction>} A promise that resolves to the signed transaction.
|
|
248
|
+
*/
|
|
183
249
|
async signOnlyTransaction(
|
|
184
250
|
txLike: ccc.TransactionLike,
|
|
185
251
|
): Promise<ccc.Transaction> {
|
|
@@ -194,6 +260,10 @@ export class CkbSigner extends ccc.Signer {
|
|
|
194
260
|
tx: JSON.parse(tx.stringify()),
|
|
195
261
|
signerAddress: (await this.assertConnection()).address,
|
|
196
262
|
witnessIndex: await tx.findInputIndexByLock(script, this.client),
|
|
263
|
+
witnessLastIndex: await tx.findLastInputIndexByLock(
|
|
264
|
+
script,
|
|
265
|
+
this.client,
|
|
266
|
+
),
|
|
197
267
|
},
|
|
198
268
|
"popup",
|
|
199
269
|
"/sign-ckb-raw-tx",
|
|
@@ -207,6 +277,11 @@ export class CkbSigner extends ccc.Signer {
|
|
|
207
277
|
return ccc.Transaction.from(res.tx);
|
|
208
278
|
}
|
|
209
279
|
|
|
280
|
+
/**
|
|
281
|
+
* Signs a raw message with the account.
|
|
282
|
+
* @param {string | ccc.BytesLike} message - The message to sign.
|
|
283
|
+
* @returns {Promise<string>} A promise that resolves to the signed message.
|
|
284
|
+
*/
|
|
210
285
|
async signMessageRaw(message: string | ccc.BytesLike): Promise<string> {
|
|
211
286
|
const { address } = await this.assertConnection();
|
|
212
287
|
|
|
@@ -234,7 +309,12 @@ export class CkbSigner extends ccc.Signer {
|
|
|
234
309
|
});
|
|
235
310
|
}
|
|
236
311
|
|
|
237
|
-
|
|
312
|
+
/**
|
|
313
|
+
* Saves the current connection.
|
|
314
|
+
* @private
|
|
315
|
+
* @returns {Promise<void>}
|
|
316
|
+
*/
|
|
317
|
+
private async saveConnection(): Promise<void> {
|
|
238
318
|
return this.connectionsRepo.set(
|
|
239
319
|
{
|
|
240
320
|
uri: this.getConfig().joyidAppURL,
|
|
@@ -244,7 +324,12 @@ export class CkbSigner extends ccc.Signer {
|
|
|
244
324
|
);
|
|
245
325
|
}
|
|
246
326
|
|
|
247
|
-
|
|
327
|
+
/**
|
|
328
|
+
* Restores the previous connection.
|
|
329
|
+
* @private
|
|
330
|
+
* @returns {Promise<void>}
|
|
331
|
+
*/
|
|
332
|
+
private async restoreConnection(): Promise<void> {
|
|
248
333
|
this.connection = await this.connectionsRepo.get({
|
|
249
334
|
uri: this.getConfig().joyidAppURL,
|
|
250
335
|
addressType: "ckb",
|
package/src/common/index.ts
CHANGED
|
@@ -16,6 +16,10 @@ import {
|
|
|
16
16
|
openPopup,
|
|
17
17
|
} from "@joyid/common";
|
|
18
18
|
|
|
19
|
+
/**
|
|
20
|
+
* Interface representing the return type for various Dapp request types.
|
|
21
|
+
* @interface
|
|
22
|
+
*/
|
|
19
23
|
export interface PopupReturnType {
|
|
20
24
|
[DappRequestType.Auth]: AuthResponseData;
|
|
21
25
|
[DappRequestType.SignMessage]: SignMessageResponseData;
|
|
@@ -36,6 +40,15 @@ export interface PopupReturnType {
|
|
|
36
40
|
[DappRequestType.EvmWeb2Login]: EvmWeb2LoginResponse;
|
|
37
41
|
}
|
|
38
42
|
|
|
43
|
+
/**
|
|
44
|
+
* Creates a popup window for JoyID Dapp requests.
|
|
45
|
+
* @param {string} url - The URL to open in the popup.
|
|
46
|
+
* @param {PopupConfigOptions<T> & { joyidAppURL: string }} config - The popup configuration options.
|
|
47
|
+
* @returns {Promise<PopupReturnType[T]>} A promise that resolves to the response data of the requested type.
|
|
48
|
+
* @throws {PopupNotSupportedError} If popups are not supported in the current browser.
|
|
49
|
+
* @throws {PopupCancelledError} If the popup is closed by the user.
|
|
50
|
+
* @throws {PopupTimeoutError} If the popup operation times out.
|
|
51
|
+
*/
|
|
39
52
|
export async function createPopup<T extends DappRequestType>(
|
|
40
53
|
url: string,
|
|
41
54
|
config: PopupConfigOptions<T> & { joyidAppURL: string },
|
|
@@ -1,42 +1,104 @@
|
|
|
1
1
|
import { ccc } from "@ckb-ccc/core";
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Type representing an account selector with a URI and address type.
|
|
5
|
+
* @typedef {Object} AccountSelector
|
|
6
|
+
* @property {string} uri - The URI of the account.
|
|
7
|
+
* @property {string} addressType - The address type of the account.
|
|
8
|
+
*/
|
|
3
9
|
export type AccountSelector = {
|
|
4
10
|
uri: string;
|
|
5
11
|
addressType: string;
|
|
6
12
|
};
|
|
7
13
|
|
|
8
|
-
|
|
14
|
+
/**
|
|
15
|
+
* Checks if two AccountSelectors are equal.
|
|
16
|
+
* @param {AccountSelector} a - The first account selector.
|
|
17
|
+
* @param {AccountSelector} b - The second account selector.
|
|
18
|
+
* @returns {boolean} True if the selectors are equal, false otherwise.
|
|
19
|
+
*/
|
|
20
|
+
export function isSelectorEq(a: AccountSelector, b: AccountSelector): boolean {
|
|
9
21
|
return a.uri === b.uri && a.addressType === b.addressType;
|
|
10
22
|
}
|
|
11
23
|
|
|
24
|
+
/**
|
|
25
|
+
* Type representing a connection with an address, public key, and key type.
|
|
26
|
+
* @typedef {Object} Connection
|
|
27
|
+
* @property {string} address - The address of the connection.
|
|
28
|
+
* @property {ccc.Hex} publicKey - The public key of the connection.
|
|
29
|
+
* @property {string} keyType - The key type of the connection.
|
|
30
|
+
*/
|
|
12
31
|
export type Connection = {
|
|
13
32
|
readonly address: string;
|
|
14
33
|
readonly publicKey: ccc.Hex;
|
|
15
34
|
readonly keyType: string;
|
|
16
35
|
};
|
|
17
36
|
|
|
37
|
+
/**
|
|
38
|
+
* Interface representing a repository for managing connections.
|
|
39
|
+
* @interface
|
|
40
|
+
*/
|
|
18
41
|
export interface ConnectionsRepo {
|
|
42
|
+
/**
|
|
43
|
+
* Gets a connection for the given selector.
|
|
44
|
+
* @param {AccountSelector} selector - The account selector.
|
|
45
|
+
* @returns {Promise<Connection | undefined>} A promise that resolves to the connection, if found.
|
|
46
|
+
*/
|
|
19
47
|
get(selector: AccountSelector): Promise<Connection | undefined>;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Sets a connection for the given selector.
|
|
51
|
+
* @param {AccountSelector} selector - The account selector.
|
|
52
|
+
* @param {Connection | undefined} connection - The connection to set.
|
|
53
|
+
* @returns {Promise<void>} A promise that resolves when the connection is set.
|
|
54
|
+
*/
|
|
20
55
|
set(
|
|
21
56
|
selector: AccountSelector,
|
|
22
57
|
connection: Connection | undefined,
|
|
23
58
|
): Promise<void>;
|
|
24
59
|
}
|
|
25
60
|
|
|
61
|
+
/**
|
|
62
|
+
* Class representing a local storage-based repository for managing connections.
|
|
63
|
+
* @class
|
|
64
|
+
* @implements {ConnectionsRepo}
|
|
65
|
+
*/
|
|
26
66
|
export class ConnectionsRepoLocalStorage implements ConnectionsRepo {
|
|
67
|
+
/**
|
|
68
|
+
* Creates an instance of ConnectionsRepoLocalStorage.
|
|
69
|
+
* @param {string} [storageKey="ccc-joy-id-signer"] - The local storage key.
|
|
70
|
+
*/
|
|
27
71
|
constructor(private readonly storageKey = "ccc-joy-id-signer") {}
|
|
28
72
|
|
|
73
|
+
/**
|
|
74
|
+
* Reads all connections from local storage.
|
|
75
|
+
* @returns {Promise<[AccountSelector, Connection][]>} A promise that resolves to an array of selectors and connections.
|
|
76
|
+
*/
|
|
29
77
|
async readConnections(): Promise<[AccountSelector, Connection][]> {
|
|
30
78
|
return JSON.parse(window.localStorage.getItem(this.storageKey) ?? "[]");
|
|
31
79
|
}
|
|
32
80
|
|
|
81
|
+
/**
|
|
82
|
+
* Gets a connection for the given selector.
|
|
83
|
+
* @param {AccountSelector} selector - The account selector.
|
|
84
|
+
* @returns {Promise<Connection | undefined>} A promise that resolves to the connection, if found.
|
|
85
|
+
*/
|
|
33
86
|
async get(selector: AccountSelector): Promise<Connection | undefined> {
|
|
34
87
|
return (await this.readConnections()).find(([s]) =>
|
|
35
88
|
isSelectorEq(selector, s),
|
|
36
89
|
)?.[1];
|
|
37
90
|
}
|
|
38
91
|
|
|
39
|
-
|
|
92
|
+
/**
|
|
93
|
+
* Sets a connection for the given selector.
|
|
94
|
+
* @param {AccountSelector} selector - The account selector.
|
|
95
|
+
* @param {Connection | undefined} connection - The connection to set.
|
|
96
|
+
* @returns {Promise<void>}
|
|
97
|
+
*/
|
|
98
|
+
async set(
|
|
99
|
+
selector: AccountSelector,
|
|
100
|
+
connection: Connection | undefined,
|
|
101
|
+
): Promise<void> {
|
|
40
102
|
const connections = await this.readConnections();
|
|
41
103
|
|
|
42
104
|
if (connection) {
|
package/src/evm/index.ts
CHANGED
|
@@ -7,10 +7,21 @@ import {
|
|
|
7
7
|
ConnectionsRepoLocalStorage,
|
|
8
8
|
} from "../connectionsStorage";
|
|
9
9
|
|
|
10
|
+
/**
|
|
11
|
+
* Class representing an EVM signer that extends SignerEvm from @ckb-ccc/core.
|
|
12
|
+
* @class
|
|
13
|
+
* @extends {ccc.SignerEvm}
|
|
14
|
+
*/
|
|
10
15
|
export class EvmSigner extends ccc.SignerEvm {
|
|
11
16
|
private connection?: Connection;
|
|
12
17
|
|
|
13
|
-
|
|
18
|
+
/**
|
|
19
|
+
* Ensures that the signer is connected and returns the connection.
|
|
20
|
+
* @private
|
|
21
|
+
* @throws Will throw an error if not connected.
|
|
22
|
+
* @returns {Connection} The current connection.
|
|
23
|
+
*/
|
|
24
|
+
private assertConnection(): Connection {
|
|
14
25
|
if (!this.isConnected() || !this.connection) {
|
|
15
26
|
throw new Error("Not connected");
|
|
16
27
|
}
|
|
@@ -18,6 +29,14 @@ export class EvmSigner extends ccc.SignerEvm {
|
|
|
18
29
|
return this.connection;
|
|
19
30
|
}
|
|
20
31
|
|
|
32
|
+
/**
|
|
33
|
+
* Creates an instance of EvmSigner.
|
|
34
|
+
* @param {ccc.Client} client - The client instance.
|
|
35
|
+
* @param {string} name - The name of the signer.
|
|
36
|
+
* @param {string} icon - The icon URL of the signer.
|
|
37
|
+
* @param {string} [appUri="https://app.joy.id"] - The application URI.
|
|
38
|
+
* @param {ConnectionsRepo} [connectionsRepo=new ConnectionsRepoLocalStorage()] - The connections repository.
|
|
39
|
+
*/
|
|
21
40
|
constructor(
|
|
22
41
|
client: ccc.Client,
|
|
23
42
|
private readonly name: string,
|
|
@@ -28,16 +47,11 @@ export class EvmSigner extends ccc.SignerEvm {
|
|
|
28
47
|
super(client);
|
|
29
48
|
}
|
|
30
49
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
this.appUri,
|
|
37
|
-
this.connectionsRepo,
|
|
38
|
-
);
|
|
39
|
-
}
|
|
40
|
-
|
|
50
|
+
/**
|
|
51
|
+
* Gets the configuration for JoyID.
|
|
52
|
+
* @private
|
|
53
|
+
* @returns {object} The configuration object.
|
|
54
|
+
*/
|
|
41
55
|
private getConfig() {
|
|
42
56
|
return {
|
|
43
57
|
redirectURL: location.href,
|
|
@@ -48,12 +62,20 @@ export class EvmSigner extends ccc.SignerEvm {
|
|
|
48
62
|
};
|
|
49
63
|
}
|
|
50
64
|
|
|
51
|
-
|
|
65
|
+
/**
|
|
66
|
+
* Gets the EVM account address.
|
|
67
|
+
* @returns {Promise<string>} A promise that resolves to the EVM account address.
|
|
68
|
+
*/
|
|
69
|
+
async getEvmAccount(): Promise<string> {
|
|
52
70
|
return this.assertConnection().address;
|
|
53
71
|
}
|
|
54
72
|
|
|
73
|
+
/**
|
|
74
|
+
* Connects to the provider by requesting authentication.
|
|
75
|
+
* @returns {Promise<void>} A promise that resolves when the connection is established.
|
|
76
|
+
*/
|
|
55
77
|
async connect(): Promise<void> {
|
|
56
|
-
const config =
|
|
78
|
+
const config = this.getConfig();
|
|
57
79
|
|
|
58
80
|
const res = await createPopup(buildJoyIDURL(config, "popup", "/auth"), {
|
|
59
81
|
...config,
|
|
@@ -68,6 +90,10 @@ export class EvmSigner extends ccc.SignerEvm {
|
|
|
68
90
|
await this.saveConnection();
|
|
69
91
|
}
|
|
70
92
|
|
|
93
|
+
/**
|
|
94
|
+
* Checks if the signer is connected.
|
|
95
|
+
* @returns {Promise<boolean>} A promise that resolves to true if connected, false otherwise.
|
|
96
|
+
*/
|
|
71
97
|
async isConnected(): Promise<boolean> {
|
|
72
98
|
if (this.connection) {
|
|
73
99
|
return true;
|
|
@@ -76,6 +102,11 @@ export class EvmSigner extends ccc.SignerEvm {
|
|
|
76
102
|
return this.connection !== undefined;
|
|
77
103
|
}
|
|
78
104
|
|
|
105
|
+
/**
|
|
106
|
+
* Signs a raw message with the EVM account.
|
|
107
|
+
* @param {string | ccc.BytesLike} message - The message to sign.
|
|
108
|
+
* @returns {Promise<ccc.Hex>} A promise that resolves to the signed message.
|
|
109
|
+
*/
|
|
79
110
|
async signMessageRaw(message: string | ccc.BytesLike): Promise<ccc.Hex> {
|
|
80
111
|
const { address } = this.assertConnection();
|
|
81
112
|
|
|
@@ -99,7 +130,12 @@ export class EvmSigner extends ccc.SignerEvm {
|
|
|
99
130
|
return ccc.hexFrom(signature);
|
|
100
131
|
}
|
|
101
132
|
|
|
102
|
-
|
|
133
|
+
/**
|
|
134
|
+
* Saves the current connection.
|
|
135
|
+
* @private
|
|
136
|
+
* @returns {Promise<void>}
|
|
137
|
+
*/
|
|
138
|
+
private async saveConnection(): Promise<void> {
|
|
103
139
|
return this.connectionsRepo.set(
|
|
104
140
|
{
|
|
105
141
|
uri: this.getConfig().joyidAppURL,
|
|
@@ -109,7 +145,12 @@ export class EvmSigner extends ccc.SignerEvm {
|
|
|
109
145
|
);
|
|
110
146
|
}
|
|
111
147
|
|
|
112
|
-
|
|
148
|
+
/**
|
|
149
|
+
* Restores the previous connection.
|
|
150
|
+
* @private
|
|
151
|
+
* @returns {Promise<void>}
|
|
152
|
+
*/
|
|
153
|
+
private async restoreConnection(): Promise<void> {
|
|
113
154
|
this.connection = await this.connectionsRepo.get({
|
|
114
155
|
uri: this.getConfig().joyidAppURL,
|
|
115
156
|
addressType: "ethereum",
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { ccc } from "@ckb-ccc/core";
|
|
2
|
+
import { DappRequestType, buildJoyIDURL } from "@joyid/common";
|
|
3
|
+
import { createPopup } from "../common";
|
|
4
|
+
import {
|
|
5
|
+
Connection,
|
|
6
|
+
ConnectionsRepo,
|
|
7
|
+
ConnectionsRepoLocalStorage,
|
|
8
|
+
} from "../connectionsStorage";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Class representing a Nostr signer that extends SignerNostr from @ckb-ccc/core.
|
|
12
|
+
* @class
|
|
13
|
+
* @extends {ccc.SignerNostr}
|
|
14
|
+
*/
|
|
15
|
+
export class NostrSigner extends ccc.SignerNostr {
|
|
16
|
+
private connection?: Connection;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Ensures that the signer is connected and returns the connection.
|
|
20
|
+
* @private
|
|
21
|
+
* @throws Will throw an error if not connected.
|
|
22
|
+
* @returns {Connection} The current connection.
|
|
23
|
+
*/
|
|
24
|
+
private assertConnection(): Connection {
|
|
25
|
+
if (!this.isConnected() || !this.connection) {
|
|
26
|
+
throw new Error("Not connected");
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return this.connection;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Creates an instance of NostrSigner.
|
|
34
|
+
* @param {ccc.Client} client - The client instance.
|
|
35
|
+
* @param {string} name - The name of the signer.
|
|
36
|
+
* @param {string} icon - The icon URL of the signer.
|
|
37
|
+
* @param {string} [appUri="https://app.joy.id"] - The application URI.
|
|
38
|
+
* @param {ConnectionsRepo} [connectionsRepo=new ConnectionsRepoLocalStorage()] - The connections repository.
|
|
39
|
+
*/
|
|
40
|
+
constructor(
|
|
41
|
+
client: ccc.Client,
|
|
42
|
+
private readonly name: string,
|
|
43
|
+
private readonly icon: string,
|
|
44
|
+
private readonly appUri = "https://app.joy.id",
|
|
45
|
+
private readonly connectionsRepo: ConnectionsRepo = new ConnectionsRepoLocalStorage(),
|
|
46
|
+
) {
|
|
47
|
+
super(client);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
static isValidClient(client: ccc.Client): boolean {
|
|
51
|
+
return client.addressPrefix === "ckt";
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
async replaceClient(client: ccc.Client): Promise<boolean> {
|
|
55
|
+
if (!NostrSigner.isValidClient(client)) {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
return super.replaceClient(client);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Gets the configuration for JoyID.
|
|
63
|
+
* @private
|
|
64
|
+
* @returns {object} The configuration object.
|
|
65
|
+
*/
|
|
66
|
+
private getConfig() {
|
|
67
|
+
return {
|
|
68
|
+
redirectURL: location.href,
|
|
69
|
+
joyidAppURL: this.appUri,
|
|
70
|
+
requestNetwork: "nostr",
|
|
71
|
+
name: this.name,
|
|
72
|
+
logo: this.icon,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Connects to the provider by requesting authentication.
|
|
78
|
+
* @returns {Promise<void>} A promise that resolves when the connection is established.
|
|
79
|
+
*/
|
|
80
|
+
async connect(): Promise<void> {
|
|
81
|
+
const config = this.getConfig();
|
|
82
|
+
const res = await createPopup(buildJoyIDURL(config, "popup", "/auth"), {
|
|
83
|
+
...config,
|
|
84
|
+
type: DappRequestType.Auth,
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
this.connection = {
|
|
88
|
+
address: "",
|
|
89
|
+
publicKey: ccc.hexFrom(res.nostrPubkey),
|
|
90
|
+
keyType: res.keyType,
|
|
91
|
+
};
|
|
92
|
+
await this.connectionsRepo.set(
|
|
93
|
+
{ uri: this.appUri, addressType: "nostr" },
|
|
94
|
+
this.connection,
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Checks if the signer is connected.
|
|
100
|
+
* @returns {Promise<boolean>} A promise that resolves to true if connected, false otherwise.
|
|
101
|
+
*/
|
|
102
|
+
async isConnected(): Promise<boolean> {
|
|
103
|
+
if (this.connection) {
|
|
104
|
+
return true;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
this.connection = await this.connectionsRepo.get({
|
|
108
|
+
uri: this.appUri,
|
|
109
|
+
addressType: "nostr",
|
|
110
|
+
});
|
|
111
|
+
return this.connection !== undefined;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
async getNostrPublicKey(): Promise<ccc.Hex> {
|
|
115
|
+
if (!this.connection) {
|
|
116
|
+
throw new Error("Not connected");
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return this.connection.publicKey;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
async signNostrEvent(
|
|
123
|
+
event: ccc.NostrEvent,
|
|
124
|
+
): Promise<Required<ccc.NostrEvent>> {
|
|
125
|
+
const config = this.getConfig();
|
|
126
|
+
const res = await createPopup(
|
|
127
|
+
buildJoyIDURL({ ...config, event }, "popup", "/sign-nostr-event"),
|
|
128
|
+
{
|
|
129
|
+
...config,
|
|
130
|
+
type: DappRequestType.SignNostrEvent,
|
|
131
|
+
},
|
|
132
|
+
);
|
|
133
|
+
return res.event;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
@@ -3,14 +3,33 @@ import { isStandaloneBrowser } from "@joyid/common";
|
|
|
3
3
|
import { BitcoinSigner } from "../btc";
|
|
4
4
|
import { CkbSigner } from "../ckb";
|
|
5
5
|
import { EvmSigner } from "../evm";
|
|
6
|
+
import { NostrSigner } from "../nostr";
|
|
6
7
|
|
|
8
|
+
/**
|
|
9
|
+
* Gets the JoyID signers based on the client, name, and icon.
|
|
10
|
+
* If the browser is standalone or a webview, returns SignerAlwaysError instances.
|
|
11
|
+
* Otherwise, returns instances of CkbSigner, BitcoinSigner, and EvmSigner.
|
|
12
|
+
* @param {ccc.Client} client - The client instance.
|
|
13
|
+
* @param {string} name - The name of the signer.
|
|
14
|
+
* @param {string} icon - The icon URL of the signer.
|
|
15
|
+
* @returns {ccc.SignerInfo[]} An array of signer information objects.
|
|
16
|
+
*/
|
|
7
17
|
export function getJoyIdSigners(
|
|
8
18
|
client: ccc.Client,
|
|
9
19
|
name: string,
|
|
10
20
|
icon: string,
|
|
11
21
|
): ccc.SignerInfo[] {
|
|
12
|
-
if (isStandaloneBrowser()) {
|
|
13
|
-
return []
|
|
22
|
+
if (isStandaloneBrowser() || ccc.isWebview(window.navigator.userAgent)) {
|
|
23
|
+
return [ccc.SignerType.CKB, ccc.SignerType.EVM, ccc.SignerType.BTC].map(
|
|
24
|
+
(type) => ({
|
|
25
|
+
name: type,
|
|
26
|
+
signer: new ccc.SignerAlwaysError(
|
|
27
|
+
client,
|
|
28
|
+
type,
|
|
29
|
+
"JoyID can only be used with standard browsers",
|
|
30
|
+
),
|
|
31
|
+
}),
|
|
32
|
+
);
|
|
14
33
|
}
|
|
15
34
|
|
|
16
35
|
return [
|
|
@@ -22,6 +41,10 @@ export function getJoyIdSigners(
|
|
|
22
41
|
name: "BTC",
|
|
23
42
|
signer: new BitcoinSigner(client, name, icon),
|
|
24
43
|
},
|
|
44
|
+
{
|
|
45
|
+
name: "Nostr",
|
|
46
|
+
signer: new NostrSigner(client, name, icon),
|
|
47
|
+
},
|
|
25
48
|
{
|
|
26
49
|
name: "EVM",
|
|
27
50
|
signer: new EvmSigner(client, name, icon),
|