Skip to content

Commit a12b9a9

Browse files
committed
feat(core): Signer.fromSignature
1 parent 72ceaf9 commit a12b9a9

File tree

4 files changed

+101
-0
lines changed

4 files changed

+101
-0
lines changed

.changeset/fifty-planes-fetch.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"@ckb-ccc/core": minor
3+
---
4+
5+
feat(core): `Signer.fromSignature`
6+

packages/core/src/signer/index.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,22 @@ export * from "./dummy/index.js";
55
export * from "./evm/index.js";
66
export * from "./nostr/index.js";
77
export * from "./signer/index.js";
8+
export * from "./signerFromSignature.js";
9+
10+
import { BytesLike } from "../bytes/index.js";
11+
import { Client } from "../client/index.js";
12+
import { Signature, Signer } from "./signer/index.js";
13+
import { signerFromSignature } from "./signerFromSignature.js";
14+
15+
export abstract class CompletedSigner extends Signer {
16+
static fromSignature(
17+
client: Client,
18+
signature: Signature,
19+
message?: string | BytesLike | null,
20+
...addresses: (string | string[])[]
21+
): Promise<Signer | undefined> {
22+
return signerFromSignature(client, signature, message, ...addresses);
23+
}
24+
}
25+
26+
export { CompletedSigner as Signer };

packages/core/src/signer/signer/index.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,17 @@ export abstract class Signer {
157157
}
158158
}
159159

160+
static async fromSignature(
161+
_client: Client,
162+
_signature: Signature,
163+
_message?: string | BytesLike | null,
164+
..._addresses: (string | string[])[]
165+
): Promise<Signer | undefined> {
166+
throw Error(
167+
"Signer.fromSignature should be override to avoid circular references",
168+
);
169+
}
170+
160171
/**
161172
* Connects to the signer.
162173
*
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import { Address } from "../address/index.js";
2+
import { BytesLike } from "../bytes/index.js";
3+
import { Client } from "../client/index.js";
4+
import { SignerBtcPublicKeyReadonly } from "./btc/index.js";
5+
import { SignerCkbPublicKey, SignerCkbScriptReadonly } from "./ckb/index.js";
6+
import { SignerDogeAddressReadonly } from "./doge/index.js";
7+
import { SignerEvmAddressReadonly } from "./evm/index.js";
8+
import { SignerNostrPublicKeyReadonly } from "./nostr/index.js";
9+
import { Signature, Signer, SignerSignType } from "./signer/index.js";
10+
11+
/**
12+
* Creates a signer from a signature.
13+
*
14+
* @param client - The client instance.
15+
* @param signature - The signature to create the signer from.
16+
* @param message - The message that was signed.
17+
* @param addresses - The addresses to check against the signer.
18+
* @returns The signer if the signature is valid and the addresses match, otherwise undefined.
19+
* @throws Error if the signature sign type is unknown.
20+
*/
21+
export async function signerFromSignature(
22+
client: Client,
23+
signature: Signature,
24+
message?: string | BytesLike | null,
25+
...addresses: (string | string[])[]
26+
): Promise<Signer | undefined> {
27+
if (
28+
message != undefined &&
29+
!(await Signer.verifyMessage(message, signature))
30+
) {
31+
return;
32+
}
33+
34+
const signer = await (async () => {
35+
switch (signature.signType) {
36+
case SignerSignType.EvmPersonal:
37+
return new SignerEvmAddressReadonly(client, signature.identity);
38+
case SignerSignType.BtcEcdsa:
39+
return new SignerBtcPublicKeyReadonly(client, "", signature.identity);
40+
case SignerSignType.JoyId: {
41+
const { address } = JSON.parse(signature.identity) as {
42+
address: string;
43+
};
44+
return new SignerCkbScriptReadonly(
45+
client,
46+
(await Address.fromString(address, client)).script,
47+
);
48+
}
49+
case SignerSignType.NostrEvent:
50+
return new SignerNostrPublicKeyReadonly(client, signature.identity);
51+
case SignerSignType.CkbSecp256k1:
52+
return new SignerCkbPublicKey(client, signature.identity);
53+
case SignerSignType.DogeEcdsa:
54+
return new SignerDogeAddressReadonly(client, signature.identity);
55+
case SignerSignType.Unknown:
56+
throw new Error("Unknown signer sign type");
57+
}
58+
})();
59+
const signerAddresses = await signer.getAddresses();
60+
if (!addresses.flat().every((addr) => signerAddresses.includes(addr))) {
61+
return;
62+
}
63+
64+
return signer;
65+
}

0 commit comments

Comments
 (0)