@cef-ai/wallet-signers 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,36 @@
1
+ # @cef-ai/wallet-signers
2
+
3
+ Three chain-signer implementations bound to a `@cef-ai/wallet-identity` session.
4
+
5
+ | Class | Curve | Use case | Address format |
6
+ | ---------------- | --------- | ----------------------------- | ----------------------- |
7
+ | `PolkadotSigner` | Ed25519 | Polkadot / Cere SS58 | SS58 (Cere prefix) |
8
+ | `EthersSigner` | secp256k1 | EVM (EIP-191 keccak-prefixed) | 0x-prefixed hex address |
9
+ | `SolanaSigner` | Ed25519 | Solana | base58 (Solana pubkey) |
10
+
11
+ Key material lives in `@cef-ai/wallet-identity`'s session vault — signers never hold
12
+ private keys themselves. Each signer is constructed with an `address` and an
13
+ `InternalSign` closure that identity hands out for the lifetime of the session.
14
+
15
+ ## Quick start
16
+
17
+ ```ts
18
+ import { PolkadotSigner, EthersSigner, SolanaSigner } from '@cef-ai/wallet-signers';
19
+
20
+ // `addresses` and `sign` come from `@cef-ai/wallet-identity` after register/login.
21
+ const cere = new PolkadotSigner({ address: addresses.cere, sign });
22
+ const evm = new EthersSigner({ address: addresses.evm, sign });
23
+ const sol = new SolanaSigner({ address: addresses.solana, sign });
24
+
25
+ const sig = await evm.signMessage('Hello'); // 0x-prefixed RSV signature
26
+ ```
27
+
28
+ `EthersSigner` is shaped to be drop-in for ethers v5/v6 consumers
29
+ (`getAddress`, `signMessage`); transaction signing is deferred. `PolkadotSigner`
30
+ implements the Polkadot.js `Signer` interface (id-correlated `signRaw`).
31
+ `SolanaSigner` exposes a thin `signMessage` returning the raw 64-byte Ed25519
32
+ signature.
33
+
34
+ ## Status
35
+
36
+ Workspace-internal — not published to npm.
package/dist/index.cjs ADDED
@@ -0,0 +1,139 @@
1
+ 'use strict';
2
+
3
+ var sha3 = require('@noble/hashes/sha3');
4
+ var utils = require('@noble/hashes/utils');
5
+
6
+ var __async = (__this, __arguments, generator) => {
7
+ return new Promise((resolve, reject) => {
8
+ var fulfilled = (value) => {
9
+ try {
10
+ step(generator.next(value));
11
+ } catch (e) {
12
+ reject(e);
13
+ }
14
+ };
15
+ var rejected = (value) => {
16
+ try {
17
+ step(generator.throw(value));
18
+ } catch (e) {
19
+ reject(e);
20
+ }
21
+ };
22
+ var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
23
+ step((generator = generator.apply(__this, __arguments)).next());
24
+ });
25
+ };
26
+ var EthersSigner = class {
27
+ constructor(opts) {
28
+ this.chain = "evm";
29
+ this.address = opts.address;
30
+ this.sign = opts.sign;
31
+ }
32
+ getAddress() {
33
+ return __async(this, null, function* () {
34
+ return this.address;
35
+ });
36
+ }
37
+ /**
38
+ * EIP-191 personal_sign: keccak256("\x19Ethereum Signed Message:\n" + len + msg).
39
+ * Returns a 0x-prefixed 65-byte hex string r||s||v with v ∈ {27, 28}.
40
+ */
41
+ signMessage(message) {
42
+ return __async(this, null, function* () {
43
+ const digest = ethersDigest(message);
44
+ const sig65 = yield this.sign("evm", digest);
45
+ const r = sig65.slice(0, 32);
46
+ const s = sig65.slice(32, 64);
47
+ const vLegacy = sig65[64] + 27;
48
+ return "0x" + bytesToHex(r) + bytesToHex(s) + vLegacy.toString(16).padStart(2, "0");
49
+ });
50
+ }
51
+ /**
52
+ * Conformance with the package's `ChainSigner` interface (raw byte signing,
53
+ * matches the InternalSign shape). Returns the 65-byte r||s||v as bytes.
54
+ */
55
+ signMessageRaw(message) {
56
+ return __async(this, null, function* () {
57
+ const digest = ethersDigest(message);
58
+ return this.sign("evm", digest);
59
+ });
60
+ }
61
+ };
62
+ function ethersDigest(message) {
63
+ const bytes = typeof message === "string" ? new TextEncoder().encode(message) : message;
64
+ const prefix = new TextEncoder().encode(`Ethereum Signed Message:
65
+ ${bytes.length}`);
66
+ return sha3.keccak_256(utils.concatBytes(prefix, bytes));
67
+ }
68
+ function bytesToHex(bytes) {
69
+ let out = "";
70
+ for (const b of bytes) out += b.toString(16).padStart(2, "0");
71
+ return out;
72
+ }
73
+
74
+ // src/PolkadotSigner.ts
75
+ var PolkadotSigner = class {
76
+ constructor(opts) {
77
+ this.chain = "cere";
78
+ this.nextId = 1;
79
+ this.address = opts.address;
80
+ this.sign = opts.sign;
81
+ }
82
+ signRaw(payload) {
83
+ return __async(this, null, function* () {
84
+ if (payload.type !== "ed25519") {
85
+ throw new Error(`PolkadotSigner: unsupported sig type "${payload.type}" (only ed25519)`);
86
+ }
87
+ const data = typeof payload.data === "string" ? hexToBytes(payload.data) : payload.data;
88
+ const sig = yield this.sign("cere", data);
89
+ const id = this.nextId++;
90
+ return { id, signature: "0x" + bytesToHex2(sig) };
91
+ });
92
+ }
93
+ /** ChainSigner conformance — raw bytes in, raw bytes out. */
94
+ signMessage(message) {
95
+ return __async(this, null, function* () {
96
+ return this.sign("cere", message);
97
+ });
98
+ }
99
+ };
100
+ function hexToBytes(hex) {
101
+ const s = hex.startsWith("0x") ? hex.slice(2) : hex;
102
+ if (s.length % 2 !== 0) throw new Error(`PolkadotSigner: odd-length hex "${hex}"`);
103
+ const out = new Uint8Array(s.length / 2);
104
+ for (let i = 0; i < out.length; i++) {
105
+ out[i] = parseInt(s.slice(i * 2, i * 2 + 2), 16);
106
+ }
107
+ return out;
108
+ }
109
+ function bytesToHex2(bytes) {
110
+ let out = "";
111
+ for (const b of bytes) out += b.toString(16).padStart(2, "0");
112
+ return out;
113
+ }
114
+
115
+ // src/SolanaSigner.ts
116
+ var SolanaSigner = class {
117
+ constructor(opts) {
118
+ this.chain = "solana";
119
+ this.address = opts.address;
120
+ this.sign = opts.sign;
121
+ }
122
+ /** Base58-encoded public key (same as the address). */
123
+ get publicKey() {
124
+ return this.address;
125
+ }
126
+ /** Signs a message with the Ed25519 session key. */
127
+ signMessage(message) {
128
+ return __async(this, null, function* () {
129
+ const bytes = typeof message === "string" ? new TextEncoder().encode(message) : message;
130
+ return this.sign("solana", bytes);
131
+ });
132
+ }
133
+ };
134
+
135
+ exports.EthersSigner = EthersSigner;
136
+ exports.PolkadotSigner = PolkadotSigner;
137
+ exports.SolanaSigner = SolanaSigner;
138
+ //# sourceMappingURL=index.cjs.map
139
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/EthersSigner.ts","../src/PolkadotSigner.ts","../src/SolanaSigner.ts"],"names":["keccak_256","concatBytes","bytesToHex"],"mappings":"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","file":"index.cjs","sourcesContent":["import { keccak_256 } from '@noble/hashes/sha3';\nimport { concatBytes } from '@noble/hashes/utils';\nimport type { InternalSign } from './types';\n\nexport interface EthersSignerOptions {\n /** EVM 0x address corresponding to the secp256k1 key the `sign` closure controls. */\n address: string;\n /** Closure handoff from identity. Signs payload with the chain-appropriate key. */\n sign: InternalSign;\n}\n\n/**\n * Duck-typed ethers v5/v6 signer. Implements just enough surface to drive\n * `personal_sign` (EIP-191) — transaction signing is deferred to a later cycle.\n *\n * Spec §4.2 (EVM signing via EmbedWallet), §3.6 invariant 1 (keys never reach\n * this class — only the closure-handoff `sign` does).\n */\nexport class EthersSigner {\n readonly chain = 'evm' as const;\n readonly address: string;\n private readonly sign: InternalSign;\n\n constructor(opts: EthersSignerOptions) {\n this.address = opts.address;\n this.sign = opts.sign;\n }\n\n async getAddress(): Promise<string> {\n return this.address;\n }\n\n /**\n * EIP-191 personal_sign: keccak256(\"\\x19Ethereum Signed Message:\\n\" + len + msg).\n * Returns a 0x-prefixed 65-byte hex string r||s||v with v ∈ {27, 28}.\n */\n async signMessage(message: string | Uint8Array): Promise<string> {\n const digest = ethersDigest(message);\n const sig65 = await this.sign('evm', digest);\n // The vault returns v ∈ {0, 1}. Ethereum legacy uses 27/28.\n const r = sig65.slice(0, 32);\n const s = sig65.slice(32, 64);\n const vLegacy = sig65[64] + 27;\n return '0x' + bytesToHex(r) + bytesToHex(s) + vLegacy.toString(16).padStart(2, '0');\n }\n\n /**\n * Conformance with the package's `ChainSigner` interface (raw byte signing,\n * matches the InternalSign shape). Returns the 65-byte r||s||v as bytes.\n */\n async signMessageRaw(message: Uint8Array): Promise<Uint8Array> {\n const digest = ethersDigest(message);\n return this.sign('evm', digest);\n }\n}\n\nfunction ethersDigest(message: string | Uint8Array): Uint8Array {\n const bytes = typeof message === 'string' ? new TextEncoder().encode(message) : message;\n const prefix = new TextEncoder().encode(`\\x19Ethereum Signed Message:\\n${bytes.length}`);\n return keccak_256(concatBytes(prefix, bytes));\n}\n\nfunction bytesToHex(bytes: Uint8Array): string {\n let out = '';\n for (const b of bytes) out += b.toString(16).padStart(2, '0');\n return out;\n}\n","import type { InternalSign, ChainSigner } from './types';\n\nexport interface PolkadotSignerOptions {\n /** Cere SS58 address corresponding to the Ed25519 key the `sign` closure controls. */\n address: string;\n sign: InternalSign;\n}\n\nexport interface SignerPayloadRaw {\n data: string | Uint8Array;\n address: string;\n type: 'ed25519';\n}\n\nexport interface SignerResult {\n id: number;\n signature: string; // '0x'-prefixed hex\n}\n\n/**\n * `@polkadot/api` SignerInterface-shaped adapter. Implements just `signRaw`\n * (the `ed25519_signRaw` permission from v1). Transaction-payload signing\n * (`signPayload`) lives in a later cycle.\n */\nexport class PolkadotSigner implements ChainSigner {\n readonly chain = 'cere' as const;\n readonly address: string;\n private readonly sign: InternalSign;\n private nextId = 1;\n\n constructor(opts: PolkadotSignerOptions) {\n this.address = opts.address;\n this.sign = opts.sign;\n }\n\n async signRaw(payload: SignerPayloadRaw): Promise<SignerResult> {\n if (payload.type !== 'ed25519') {\n throw new Error(`PolkadotSigner: unsupported sig type \"${payload.type}\" (only ed25519)`);\n }\n const data = typeof payload.data === 'string' ? hexToBytes(payload.data) : payload.data;\n const sig = await this.sign('cere', data);\n const id = this.nextId++;\n return { id, signature: '0x' + bytesToHex(sig) };\n }\n\n /** ChainSigner conformance — raw bytes in, raw bytes out. */\n async signMessage(message: Uint8Array): Promise<Uint8Array> {\n return this.sign('cere', message);\n }\n}\n\nfunction hexToBytes(hex: string): Uint8Array {\n const s = hex.startsWith('0x') ? hex.slice(2) : hex;\n if (s.length % 2 !== 0) throw new Error(`PolkadotSigner: odd-length hex \"${hex}\"`);\n const out = new Uint8Array(s.length / 2);\n for (let i = 0; i < out.length; i++) {\n out[i] = parseInt(s.slice(i * 2, i * 2 + 2), 16);\n }\n return out;\n}\n\nfunction bytesToHex(bytes: Uint8Array): string {\n let out = '';\n for (const b of bytes) out += b.toString(16).padStart(2, '0');\n return out;\n}\n","import type { InternalSign, ChainSigner } from './types';\n\nexport interface SolanaSignerOptions {\n /** Solana base58 address corresponding to the Ed25519 key the `sign` closure controls. */\n address: string;\n sign: InternalSign;\n}\n\n/**\n * `@solana/web3.js`-compatible adapter. Exposes only `signMessage` in this\n * cycle — the `solana_signMessage` permission. Full transaction signing\n * (interacting with `Transaction.serializeMessage`/`addSignature`) is deferred.\n */\nexport class SolanaSigner implements ChainSigner {\n readonly chain = 'solana' as const;\n readonly address: string;\n private readonly sign: InternalSign;\n\n constructor(opts: SolanaSignerOptions) {\n this.address = opts.address;\n this.sign = opts.sign;\n }\n\n /** Base58-encoded public key (same as the address). */\n get publicKey(): string {\n return this.address;\n }\n\n /** Signs a message with the Ed25519 session key. */\n async signMessage(message: string | Uint8Array): Promise<Uint8Array> {\n const bytes = typeof message === 'string' ? new TextEncoder().encode(message) : message;\n return this.sign('solana', bytes);\n }\n}\n"]}
@@ -0,0 +1,92 @@
1
+ import { Chain, InternalSign } from '@cef-ai/wallet-identity';
2
+ export { InternalSign } from '@cef-ai/wallet-identity';
3
+
4
+ interface ChainSigner {
5
+ readonly chain: Chain;
6
+ readonly address: string;
7
+ signMessage(message: Uint8Array): Promise<Uint8Array>;
8
+ }
9
+
10
+ interface EthersSignerOptions {
11
+ /** EVM 0x address corresponding to the secp256k1 key the `sign` closure controls. */
12
+ address: string;
13
+ /** Closure handoff from identity. Signs payload with the chain-appropriate key. */
14
+ sign: InternalSign;
15
+ }
16
+ /**
17
+ * Duck-typed ethers v5/v6 signer. Implements just enough surface to drive
18
+ * `personal_sign` (EIP-191) — transaction signing is deferred to a later cycle.
19
+ *
20
+ * Spec §4.2 (EVM signing via EmbedWallet), §3.6 invariant 1 (keys never reach
21
+ * this class — only the closure-handoff `sign` does).
22
+ */
23
+ declare class EthersSigner {
24
+ readonly chain: "evm";
25
+ readonly address: string;
26
+ private readonly sign;
27
+ constructor(opts: EthersSignerOptions);
28
+ getAddress(): Promise<string>;
29
+ /**
30
+ * EIP-191 personal_sign: keccak256("\x19Ethereum Signed Message:\n" + len + msg).
31
+ * Returns a 0x-prefixed 65-byte hex string r||s||v with v ∈ {27, 28}.
32
+ */
33
+ signMessage(message: string | Uint8Array): Promise<string>;
34
+ /**
35
+ * Conformance with the package's `ChainSigner` interface (raw byte signing,
36
+ * matches the InternalSign shape). Returns the 65-byte r||s||v as bytes.
37
+ */
38
+ signMessageRaw(message: Uint8Array): Promise<Uint8Array>;
39
+ }
40
+
41
+ interface PolkadotSignerOptions {
42
+ /** Cere SS58 address corresponding to the Ed25519 key the `sign` closure controls. */
43
+ address: string;
44
+ sign: InternalSign;
45
+ }
46
+ interface SignerPayloadRaw {
47
+ data: string | Uint8Array;
48
+ address: string;
49
+ type: 'ed25519';
50
+ }
51
+ interface SignerResult {
52
+ id: number;
53
+ signature: string;
54
+ }
55
+ /**
56
+ * `@polkadot/api` SignerInterface-shaped adapter. Implements just `signRaw`
57
+ * (the `ed25519_signRaw` permission from v1). Transaction-payload signing
58
+ * (`signPayload`) lives in a later cycle.
59
+ */
60
+ declare class PolkadotSigner implements ChainSigner {
61
+ readonly chain: "cere";
62
+ readonly address: string;
63
+ private readonly sign;
64
+ private nextId;
65
+ constructor(opts: PolkadotSignerOptions);
66
+ signRaw(payload: SignerPayloadRaw): Promise<SignerResult>;
67
+ /** ChainSigner conformance — raw bytes in, raw bytes out. */
68
+ signMessage(message: Uint8Array): Promise<Uint8Array>;
69
+ }
70
+
71
+ interface SolanaSignerOptions {
72
+ /** Solana base58 address corresponding to the Ed25519 key the `sign` closure controls. */
73
+ address: string;
74
+ sign: InternalSign;
75
+ }
76
+ /**
77
+ * `@solana/web3.js`-compatible adapter. Exposes only `signMessage` in this
78
+ * cycle — the `solana_signMessage` permission. Full transaction signing
79
+ * (interacting with `Transaction.serializeMessage`/`addSignature`) is deferred.
80
+ */
81
+ declare class SolanaSigner implements ChainSigner {
82
+ readonly chain: "solana";
83
+ readonly address: string;
84
+ private readonly sign;
85
+ constructor(opts: SolanaSignerOptions);
86
+ /** Base58-encoded public key (same as the address). */
87
+ get publicKey(): string;
88
+ /** Signs a message with the Ed25519 session key. */
89
+ signMessage(message: string | Uint8Array): Promise<Uint8Array>;
90
+ }
91
+
92
+ export { type ChainSigner, EthersSigner, type EthersSignerOptions, PolkadotSigner, type PolkadotSignerOptions, type SignerPayloadRaw, type SignerResult, SolanaSigner, type SolanaSignerOptions };
@@ -0,0 +1,92 @@
1
+ import { Chain, InternalSign } from '@cef-ai/wallet-identity';
2
+ export { InternalSign } from '@cef-ai/wallet-identity';
3
+
4
+ interface ChainSigner {
5
+ readonly chain: Chain;
6
+ readonly address: string;
7
+ signMessage(message: Uint8Array): Promise<Uint8Array>;
8
+ }
9
+
10
+ interface EthersSignerOptions {
11
+ /** EVM 0x address corresponding to the secp256k1 key the `sign` closure controls. */
12
+ address: string;
13
+ /** Closure handoff from identity. Signs payload with the chain-appropriate key. */
14
+ sign: InternalSign;
15
+ }
16
+ /**
17
+ * Duck-typed ethers v5/v6 signer. Implements just enough surface to drive
18
+ * `personal_sign` (EIP-191) — transaction signing is deferred to a later cycle.
19
+ *
20
+ * Spec §4.2 (EVM signing via EmbedWallet), §3.6 invariant 1 (keys never reach
21
+ * this class — only the closure-handoff `sign` does).
22
+ */
23
+ declare class EthersSigner {
24
+ readonly chain: "evm";
25
+ readonly address: string;
26
+ private readonly sign;
27
+ constructor(opts: EthersSignerOptions);
28
+ getAddress(): Promise<string>;
29
+ /**
30
+ * EIP-191 personal_sign: keccak256("\x19Ethereum Signed Message:\n" + len + msg).
31
+ * Returns a 0x-prefixed 65-byte hex string r||s||v with v ∈ {27, 28}.
32
+ */
33
+ signMessage(message: string | Uint8Array): Promise<string>;
34
+ /**
35
+ * Conformance with the package's `ChainSigner` interface (raw byte signing,
36
+ * matches the InternalSign shape). Returns the 65-byte r||s||v as bytes.
37
+ */
38
+ signMessageRaw(message: Uint8Array): Promise<Uint8Array>;
39
+ }
40
+
41
+ interface PolkadotSignerOptions {
42
+ /** Cere SS58 address corresponding to the Ed25519 key the `sign` closure controls. */
43
+ address: string;
44
+ sign: InternalSign;
45
+ }
46
+ interface SignerPayloadRaw {
47
+ data: string | Uint8Array;
48
+ address: string;
49
+ type: 'ed25519';
50
+ }
51
+ interface SignerResult {
52
+ id: number;
53
+ signature: string;
54
+ }
55
+ /**
56
+ * `@polkadot/api` SignerInterface-shaped adapter. Implements just `signRaw`
57
+ * (the `ed25519_signRaw` permission from v1). Transaction-payload signing
58
+ * (`signPayload`) lives in a later cycle.
59
+ */
60
+ declare class PolkadotSigner implements ChainSigner {
61
+ readonly chain: "cere";
62
+ readonly address: string;
63
+ private readonly sign;
64
+ private nextId;
65
+ constructor(opts: PolkadotSignerOptions);
66
+ signRaw(payload: SignerPayloadRaw): Promise<SignerResult>;
67
+ /** ChainSigner conformance — raw bytes in, raw bytes out. */
68
+ signMessage(message: Uint8Array): Promise<Uint8Array>;
69
+ }
70
+
71
+ interface SolanaSignerOptions {
72
+ /** Solana base58 address corresponding to the Ed25519 key the `sign` closure controls. */
73
+ address: string;
74
+ sign: InternalSign;
75
+ }
76
+ /**
77
+ * `@solana/web3.js`-compatible adapter. Exposes only `signMessage` in this
78
+ * cycle — the `solana_signMessage` permission. Full transaction signing
79
+ * (interacting with `Transaction.serializeMessage`/`addSignature`) is deferred.
80
+ */
81
+ declare class SolanaSigner implements ChainSigner {
82
+ readonly chain: "solana";
83
+ readonly address: string;
84
+ private readonly sign;
85
+ constructor(opts: SolanaSignerOptions);
86
+ /** Base58-encoded public key (same as the address). */
87
+ get publicKey(): string;
88
+ /** Signs a message with the Ed25519 session key. */
89
+ signMessage(message: string | Uint8Array): Promise<Uint8Array>;
90
+ }
91
+
92
+ export { type ChainSigner, EthersSigner, type EthersSignerOptions, PolkadotSigner, type PolkadotSignerOptions, type SignerPayloadRaw, type SignerResult, SolanaSigner, type SolanaSignerOptions };
package/dist/index.js ADDED
@@ -0,0 +1,135 @@
1
+ import { keccak_256 } from '@noble/hashes/sha3';
2
+ import { concatBytes } from '@noble/hashes/utils';
3
+
4
+ var __async = (__this, __arguments, generator) => {
5
+ return new Promise((resolve, reject) => {
6
+ var fulfilled = (value) => {
7
+ try {
8
+ step(generator.next(value));
9
+ } catch (e) {
10
+ reject(e);
11
+ }
12
+ };
13
+ var rejected = (value) => {
14
+ try {
15
+ step(generator.throw(value));
16
+ } catch (e) {
17
+ reject(e);
18
+ }
19
+ };
20
+ var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
21
+ step((generator = generator.apply(__this, __arguments)).next());
22
+ });
23
+ };
24
+ var EthersSigner = class {
25
+ constructor(opts) {
26
+ this.chain = "evm";
27
+ this.address = opts.address;
28
+ this.sign = opts.sign;
29
+ }
30
+ getAddress() {
31
+ return __async(this, null, function* () {
32
+ return this.address;
33
+ });
34
+ }
35
+ /**
36
+ * EIP-191 personal_sign: keccak256("\x19Ethereum Signed Message:\n" + len + msg).
37
+ * Returns a 0x-prefixed 65-byte hex string r||s||v with v ∈ {27, 28}.
38
+ */
39
+ signMessage(message) {
40
+ return __async(this, null, function* () {
41
+ const digest = ethersDigest(message);
42
+ const sig65 = yield this.sign("evm", digest);
43
+ const r = sig65.slice(0, 32);
44
+ const s = sig65.slice(32, 64);
45
+ const vLegacy = sig65[64] + 27;
46
+ return "0x" + bytesToHex(r) + bytesToHex(s) + vLegacy.toString(16).padStart(2, "0");
47
+ });
48
+ }
49
+ /**
50
+ * Conformance with the package's `ChainSigner` interface (raw byte signing,
51
+ * matches the InternalSign shape). Returns the 65-byte r||s||v as bytes.
52
+ */
53
+ signMessageRaw(message) {
54
+ return __async(this, null, function* () {
55
+ const digest = ethersDigest(message);
56
+ return this.sign("evm", digest);
57
+ });
58
+ }
59
+ };
60
+ function ethersDigest(message) {
61
+ const bytes = typeof message === "string" ? new TextEncoder().encode(message) : message;
62
+ const prefix = new TextEncoder().encode(`Ethereum Signed Message:
63
+ ${bytes.length}`);
64
+ return keccak_256(concatBytes(prefix, bytes));
65
+ }
66
+ function bytesToHex(bytes) {
67
+ let out = "";
68
+ for (const b of bytes) out += b.toString(16).padStart(2, "0");
69
+ return out;
70
+ }
71
+
72
+ // src/PolkadotSigner.ts
73
+ var PolkadotSigner = class {
74
+ constructor(opts) {
75
+ this.chain = "cere";
76
+ this.nextId = 1;
77
+ this.address = opts.address;
78
+ this.sign = opts.sign;
79
+ }
80
+ signRaw(payload) {
81
+ return __async(this, null, function* () {
82
+ if (payload.type !== "ed25519") {
83
+ throw new Error(`PolkadotSigner: unsupported sig type "${payload.type}" (only ed25519)`);
84
+ }
85
+ const data = typeof payload.data === "string" ? hexToBytes(payload.data) : payload.data;
86
+ const sig = yield this.sign("cere", data);
87
+ const id = this.nextId++;
88
+ return { id, signature: "0x" + bytesToHex2(sig) };
89
+ });
90
+ }
91
+ /** ChainSigner conformance — raw bytes in, raw bytes out. */
92
+ signMessage(message) {
93
+ return __async(this, null, function* () {
94
+ return this.sign("cere", message);
95
+ });
96
+ }
97
+ };
98
+ function hexToBytes(hex) {
99
+ const s = hex.startsWith("0x") ? hex.slice(2) : hex;
100
+ if (s.length % 2 !== 0) throw new Error(`PolkadotSigner: odd-length hex "${hex}"`);
101
+ const out = new Uint8Array(s.length / 2);
102
+ for (let i = 0; i < out.length; i++) {
103
+ out[i] = parseInt(s.slice(i * 2, i * 2 + 2), 16);
104
+ }
105
+ return out;
106
+ }
107
+ function bytesToHex2(bytes) {
108
+ let out = "";
109
+ for (const b of bytes) out += b.toString(16).padStart(2, "0");
110
+ return out;
111
+ }
112
+
113
+ // src/SolanaSigner.ts
114
+ var SolanaSigner = class {
115
+ constructor(opts) {
116
+ this.chain = "solana";
117
+ this.address = opts.address;
118
+ this.sign = opts.sign;
119
+ }
120
+ /** Base58-encoded public key (same as the address). */
121
+ get publicKey() {
122
+ return this.address;
123
+ }
124
+ /** Signs a message with the Ed25519 session key. */
125
+ signMessage(message) {
126
+ return __async(this, null, function* () {
127
+ const bytes = typeof message === "string" ? new TextEncoder().encode(message) : message;
128
+ return this.sign("solana", bytes);
129
+ });
130
+ }
131
+ };
132
+
133
+ export { EthersSigner, PolkadotSigner, SolanaSigner };
134
+ //# sourceMappingURL=index.js.map
135
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/EthersSigner.ts","../src/PolkadotSigner.ts","../src/SolanaSigner.ts"],"names":["bytesToHex"],"mappings":"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","file":"index.js","sourcesContent":["import { keccak_256 } from '@noble/hashes/sha3';\nimport { concatBytes } from '@noble/hashes/utils';\nimport type { InternalSign } from './types';\n\nexport interface EthersSignerOptions {\n /** EVM 0x address corresponding to the secp256k1 key the `sign` closure controls. */\n address: string;\n /** Closure handoff from identity. Signs payload with the chain-appropriate key. */\n sign: InternalSign;\n}\n\n/**\n * Duck-typed ethers v5/v6 signer. Implements just enough surface to drive\n * `personal_sign` (EIP-191) — transaction signing is deferred to a later cycle.\n *\n * Spec §4.2 (EVM signing via EmbedWallet), §3.6 invariant 1 (keys never reach\n * this class — only the closure-handoff `sign` does).\n */\nexport class EthersSigner {\n readonly chain = 'evm' as const;\n readonly address: string;\n private readonly sign: InternalSign;\n\n constructor(opts: EthersSignerOptions) {\n this.address = opts.address;\n this.sign = opts.sign;\n }\n\n async getAddress(): Promise<string> {\n return this.address;\n }\n\n /**\n * EIP-191 personal_sign: keccak256(\"\\x19Ethereum Signed Message:\\n\" + len + msg).\n * Returns a 0x-prefixed 65-byte hex string r||s||v with v ∈ {27, 28}.\n */\n async signMessage(message: string | Uint8Array): Promise<string> {\n const digest = ethersDigest(message);\n const sig65 = await this.sign('evm', digest);\n // The vault returns v ∈ {0, 1}. Ethereum legacy uses 27/28.\n const r = sig65.slice(0, 32);\n const s = sig65.slice(32, 64);\n const vLegacy = sig65[64] + 27;\n return '0x' + bytesToHex(r) + bytesToHex(s) + vLegacy.toString(16).padStart(2, '0');\n }\n\n /**\n * Conformance with the package's `ChainSigner` interface (raw byte signing,\n * matches the InternalSign shape). Returns the 65-byte r||s||v as bytes.\n */\n async signMessageRaw(message: Uint8Array): Promise<Uint8Array> {\n const digest = ethersDigest(message);\n return this.sign('evm', digest);\n }\n}\n\nfunction ethersDigest(message: string | Uint8Array): Uint8Array {\n const bytes = typeof message === 'string' ? new TextEncoder().encode(message) : message;\n const prefix = new TextEncoder().encode(`\\x19Ethereum Signed Message:\\n${bytes.length}`);\n return keccak_256(concatBytes(prefix, bytes));\n}\n\nfunction bytesToHex(bytes: Uint8Array): string {\n let out = '';\n for (const b of bytes) out += b.toString(16).padStart(2, '0');\n return out;\n}\n","import type { InternalSign, ChainSigner } from './types';\n\nexport interface PolkadotSignerOptions {\n /** Cere SS58 address corresponding to the Ed25519 key the `sign` closure controls. */\n address: string;\n sign: InternalSign;\n}\n\nexport interface SignerPayloadRaw {\n data: string | Uint8Array;\n address: string;\n type: 'ed25519';\n}\n\nexport interface SignerResult {\n id: number;\n signature: string; // '0x'-prefixed hex\n}\n\n/**\n * `@polkadot/api` SignerInterface-shaped adapter. Implements just `signRaw`\n * (the `ed25519_signRaw` permission from v1). Transaction-payload signing\n * (`signPayload`) lives in a later cycle.\n */\nexport class PolkadotSigner implements ChainSigner {\n readonly chain = 'cere' as const;\n readonly address: string;\n private readonly sign: InternalSign;\n private nextId = 1;\n\n constructor(opts: PolkadotSignerOptions) {\n this.address = opts.address;\n this.sign = opts.sign;\n }\n\n async signRaw(payload: SignerPayloadRaw): Promise<SignerResult> {\n if (payload.type !== 'ed25519') {\n throw new Error(`PolkadotSigner: unsupported sig type \"${payload.type}\" (only ed25519)`);\n }\n const data = typeof payload.data === 'string' ? hexToBytes(payload.data) : payload.data;\n const sig = await this.sign('cere', data);\n const id = this.nextId++;\n return { id, signature: '0x' + bytesToHex(sig) };\n }\n\n /** ChainSigner conformance — raw bytes in, raw bytes out. */\n async signMessage(message: Uint8Array): Promise<Uint8Array> {\n return this.sign('cere', message);\n }\n}\n\nfunction hexToBytes(hex: string): Uint8Array {\n const s = hex.startsWith('0x') ? hex.slice(2) : hex;\n if (s.length % 2 !== 0) throw new Error(`PolkadotSigner: odd-length hex \"${hex}\"`);\n const out = new Uint8Array(s.length / 2);\n for (let i = 0; i < out.length; i++) {\n out[i] = parseInt(s.slice(i * 2, i * 2 + 2), 16);\n }\n return out;\n}\n\nfunction bytesToHex(bytes: Uint8Array): string {\n let out = '';\n for (const b of bytes) out += b.toString(16).padStart(2, '0');\n return out;\n}\n","import type { InternalSign, ChainSigner } from './types';\n\nexport interface SolanaSignerOptions {\n /** Solana base58 address corresponding to the Ed25519 key the `sign` closure controls. */\n address: string;\n sign: InternalSign;\n}\n\n/**\n * `@solana/web3.js`-compatible adapter. Exposes only `signMessage` in this\n * cycle — the `solana_signMessage` permission. Full transaction signing\n * (interacting with `Transaction.serializeMessage`/`addSignature`) is deferred.\n */\nexport class SolanaSigner implements ChainSigner {\n readonly chain = 'solana' as const;\n readonly address: string;\n private readonly sign: InternalSign;\n\n constructor(opts: SolanaSignerOptions) {\n this.address = opts.address;\n this.sign = opts.sign;\n }\n\n /** Base58-encoded public key (same as the address). */\n get publicKey(): string {\n return this.address;\n }\n\n /** Signs a message with the Ed25519 session key. */\n async signMessage(message: string | Uint8Array): Promise<Uint8Array> {\n const bytes = typeof message === 'string' ? new TextEncoder().encode(message) : message;\n return this.sign('solana', bytes);\n }\n}\n"]}
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "@cef-ai/wallet-signers",
3
+ "version": "1.0.0",
4
+ "description": "Per-chain signers for SCP Wallet (Ethers, Polkadot, Solana) over a passkey-derived identity.",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/cere-io/cere-wallet-client.git",
9
+ "directory": "packages/signers"
10
+ },
11
+ "sideEffects": false,
12
+ "type": "module",
13
+ "types": "./dist/index.d.ts",
14
+ "exports": {
15
+ ".": {
16
+ "import": {
17
+ "types": "./dist/index.d.ts",
18
+ "default": "./dist/index.js"
19
+ },
20
+ "require": {
21
+ "types": "./dist/index.d.cts",
22
+ "default": "./dist/index.cjs"
23
+ }
24
+ }
25
+ },
26
+ "files": [
27
+ "dist",
28
+ "README.md"
29
+ ],
30
+ "dependencies": {
31
+ "@noble/curves": "^1.6.0",
32
+ "@noble/hashes": "^1.5.0",
33
+ "@cef-ai/wallet-identity": "1.0.0"
34
+ },
35
+ "devDependencies": {},
36
+ "scripts": {
37
+ "test": "vitest run",
38
+ "check-types": "tsc --noEmit",
39
+ "build": "tsup"
40
+ },
41
+ "main": "./dist/index.cjs",
42
+ "module": "./dist/index.js"
43
+ }