cruzo-web3 0.1.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 +242 -0
- package/lib/components/icons/copy-icon.component.ts +14 -0
- package/lib/components/web3-signer/web3-signer.component.module.css +106 -0
- package/lib/components/web3-signer/web3-signer.component.ts +320 -0
- package/lib/components/web3-signing/web3-signing.component.module.css +36 -0
- package/lib/components/web3-signing/web3-signing.component.ts +239 -0
- package/lib/components/web3-wallet-picker/web3-wallet-picker.bucket.ts +22 -0
- package/lib/components/web3-wallet-picker/web3-wallet-picker.component.module.css +62 -0
- package/lib/components/web3-wallet-picker/web3-wallet-picker.component.ts +171 -0
- package/lib/crypto/account-signature.ts +175 -0
- package/lib/crypto/decode-bytes.ts +93 -0
- package/lib/crypto/ecdsa-signature.ts +45 -0
- package/lib/crypto/keccak256.ts +117 -0
- package/lib/crypto/secp256k1-verify.ts +232 -0
- package/lib/crypto/sha256.ts +8 -0
- package/lib/crypto/verify-signature.ts +54 -0
- package/lib/env.d.ts +4 -0
- package/lib/errors/web3-error.ts +49 -0
- package/lib/index.ts +20 -0
- package/lib/providers/eip1193.provider.ts +152 -0
- package/lib/providers/injected.ts +71 -0
- package/lib/providers/message-bytes.ts +13 -0
- package/lib/providers/solana.provider.ts +116 -0
- package/lib/providers/tonconnect.provider.ts +161 -0
- package/lib/providers/tron.provider.ts +142 -0
- package/lib/providers/wallet-transport.ts +1 -0
- package/lib/providers/wallet.ts +92 -0
- package/lib/providers/walletconnect-ethereum.provider.ts +49 -0
- package/lib/pub-key.ts +144 -0
- package/lib/signing-url.ts +334 -0
- package/lib/types/signer-state.ts +10 -0
- package/lib/types/web3-types.ts +27 -0
- package/lib/utils/format-pub-key.ts +18 -0
- package/lib/web3-wallet.ts +31 -0
- package/lib/web3.service.ts +419 -0
- package/package.json +58 -0
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import type { PubKey, Web3Provider } from "../types/web3-types";
|
|
2
|
+
import { toMessageBytes } from "./message-bytes";
|
|
3
|
+
|
|
4
|
+
export interface TronWeb {
|
|
5
|
+
ready?: boolean;
|
|
6
|
+
defaultAddress?: { base58: string };
|
|
7
|
+
request?(args: { method: string; params?: unknown }): Promise<unknown>;
|
|
8
|
+
trx?: {
|
|
9
|
+
signMessageV2(message: string): Promise<string>;
|
|
10
|
+
};
|
|
11
|
+
toHex?(value: string): string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface TronLink {
|
|
15
|
+
ready?: boolean;
|
|
16
|
+
tronWeb?: TronWeb;
|
|
17
|
+
request(args: { method: string; params?: unknown }): Promise<unknown>;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
declare global {
|
|
21
|
+
interface Window {
|
|
22
|
+
tronWeb?: TronWeb;
|
|
23
|
+
tronLink?: TronLink;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function toHexMessage(message: string | Uint8Array, tronWeb?: TronWeb) {
|
|
28
|
+
const text = message instanceof Uint8Array
|
|
29
|
+
? new TextDecoder().decode(message)
|
|
30
|
+
: message;
|
|
31
|
+
|
|
32
|
+
if (tronWeb?.toHex) return tronWeb.toHex(text);
|
|
33
|
+
|
|
34
|
+
const bytes = toMessageBytes(message);
|
|
35
|
+
let hex = "";
|
|
36
|
+
|
|
37
|
+
for (const byte of bytes) {
|
|
38
|
+
hex += byte.toString(16).padStart(2, "0");
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return hex;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function getInjectedTronLink() {
|
|
45
|
+
return globalThis.window?.tronLink ?? null;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function getInjectedTronWeb() {
|
|
49
|
+
return globalThis.window?.tronWeb ?? globalThis.window?.tronLink?.tronWeb ?? null;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export class TronProvider implements Web3Provider {
|
|
53
|
+
readonly id = "tron";
|
|
54
|
+
|
|
55
|
+
constructor(
|
|
56
|
+
private tronLink: TronLink,
|
|
57
|
+
private onAccountChange?: (pubKey: PubKey) => void,
|
|
58
|
+
) {}
|
|
59
|
+
|
|
60
|
+
static fromInjected(onAccountChange?: (pubKey: PubKey) => void) {
|
|
61
|
+
const tronLink = getInjectedTronLink();
|
|
62
|
+
|
|
63
|
+
if (!tronLink) {
|
|
64
|
+
throw new Error("No injected Tron wallet found (install TronLink)");
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return new TronProvider(tronLink, onAccountChange);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async connect() {
|
|
71
|
+
await this.requestAccounts();
|
|
72
|
+
const address = this.readAddress();
|
|
73
|
+
this.onAccountChange?.(this.toPubKey(address));
|
|
74
|
+
return this.toPubKey(address);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
async disconnect() {
|
|
78
|
+
// TronLink does not expose a standard disconnect for dApps.
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
async signMessage(message: string | Uint8Array) {
|
|
82
|
+
const tronWeb = await this.requireTronWeb();
|
|
83
|
+
const signMessage = tronWeb.trx?.signMessageV2;
|
|
84
|
+
|
|
85
|
+
if (!signMessage) {
|
|
86
|
+
throw new Error("Tron wallet does not support signMessageV2");
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const address = this.readAddress();
|
|
90
|
+
const signature = await signMessage.call(tronWeb.trx, toHexMessage(message, tronWeb));
|
|
91
|
+
|
|
92
|
+
if (typeof signature !== "string" || !signature.length) {
|
|
93
|
+
throw new Error("Wallet returned an invalid signature");
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (this.readAddress() !== address) {
|
|
97
|
+
throw new Error("Connected Tron wallet account changed before signing");
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return signature.startsWith("0x") ? signature : signature;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
private async requestAccounts() {
|
|
104
|
+
const response = await this.tronLink.request({ method: "tron_requestAccounts" });
|
|
105
|
+
|
|
106
|
+
if (response && typeof response === "object" && "code" in response) {
|
|
107
|
+
const result = response as { code: number; message?: string };
|
|
108
|
+
|
|
109
|
+
if (result.code !== 200) {
|
|
110
|
+
throw new Error(result.message || "Tron wallet rejected the connection request");
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
private async requireTronWeb() {
|
|
116
|
+
const tronWeb = getInjectedTronWeb();
|
|
117
|
+
|
|
118
|
+
if (!tronWeb?.trx) {
|
|
119
|
+
throw new Error("Tron wallet is not ready");
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return tronWeb;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
private readAddress() {
|
|
126
|
+
const address = getInjectedTronWeb()?.defaultAddress?.base58;
|
|
127
|
+
|
|
128
|
+
if (!address) {
|
|
129
|
+
throw new Error("Tron wallet is not connected");
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return address;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
private toPubKey(address: string): PubKey {
|
|
136
|
+
return {
|
|
137
|
+
type: "secp256k1",
|
|
138
|
+
value: address,
|
|
139
|
+
encoding: "base58",
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type WalletTransport = "extension" | "app" | "auto";
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import type { PubKey, Web3Provider } from "../types/web3-types";
|
|
2
|
+
import { Eip1193Provider, getInjectedEthereum } from "./eip1193.provider";
|
|
3
|
+
import { createInjectedProvider, hasInjectedWallet, type InjectedWalletKind } from "./injected";
|
|
4
|
+
import { SolanaProvider } from "./solana.provider";
|
|
5
|
+
import { TonConnectProvider } from "./tonconnect.provider";
|
|
6
|
+
import { TronProvider } from "./tron.provider";
|
|
7
|
+
import { WalletConnectEthereumProvider } from "./walletconnect-ethereum.provider";
|
|
8
|
+
import type { WalletTransport } from "./wallet-transport";
|
|
9
|
+
|
|
10
|
+
export type { WalletTransport } from "./wallet-transport";
|
|
11
|
+
|
|
12
|
+
export type WalletProviderOptions = {
|
|
13
|
+
tonManifestUrl?: string;
|
|
14
|
+
walletConnectProjectId?: string;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export type WalletKind = InjectedWalletKind;
|
|
18
|
+
|
|
19
|
+
function resolveTransport(kind: WalletKind, transport: WalletTransport): WalletTransport {
|
|
20
|
+
if (transport !== "auto") return transport;
|
|
21
|
+
|
|
22
|
+
if (kind === "ethereum") {
|
|
23
|
+
return getInjectedEthereum() ? "extension" : "app";
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (kind === "ton") {
|
|
27
|
+
return hasInjectedWallet("ton") ? "extension" : "app";
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return hasInjectedWallet(kind) ? "extension" : "extension";
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export async function createWalletProvider(
|
|
34
|
+
kind: WalletKind,
|
|
35
|
+
transport: WalletTransport,
|
|
36
|
+
onAccountChange?: (pubKey: PubKey) => void,
|
|
37
|
+
options: WalletProviderOptions = {},
|
|
38
|
+
): Promise<Web3Provider> {
|
|
39
|
+
const resolved = resolveTransport(kind, transport);
|
|
40
|
+
|
|
41
|
+
if (kind === "ethereum" && resolved === "app") {
|
|
42
|
+
const projectId = options.walletConnectProjectId;
|
|
43
|
+
|
|
44
|
+
if (!projectId) {
|
|
45
|
+
throw new Error("Ethereum mobile wallet requires walletConnectProjectId");
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return WalletConnectEthereumProvider.create({ projectId }, onAccountChange);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (kind === "ton") {
|
|
52
|
+
const manifestUrl = options.tonManifestUrl;
|
|
53
|
+
|
|
54
|
+
if (!manifestUrl) {
|
|
55
|
+
throw new Error("TON wallet requires tonManifestUrl (Ton Connect manifest)");
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return TonConnectProvider.create(
|
|
59
|
+
{ manifestUrl, transport: resolved },
|
|
60
|
+
onAccountChange,
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (resolved === "app") {
|
|
65
|
+
throw new Error(`${kind} mobile wallet is not supported yet`);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return createInjectedProvider(kind, onAccountChange, {
|
|
69
|
+
tonManifestUrl: options.tonManifestUrl,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function getWalletModeLabel(kind: WalletKind, transport: WalletTransport = "auto") {
|
|
74
|
+
const resolved = resolveTransport(kind, transport);
|
|
75
|
+
|
|
76
|
+
if (kind === "ethereum") {
|
|
77
|
+
return resolved === "app"
|
|
78
|
+
? "Ethereum app (WalletConnect)"
|
|
79
|
+
: "Ethereum extension (MetaMask and EIP-1193 wallets)";
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (kind === "ton") {
|
|
83
|
+
return resolved === "app"
|
|
84
|
+
? "TON app (Tonkeeper and other TON wallets)"
|
|
85
|
+
: "TON extension (Tonkeeper and other TON wallets)";
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (kind === "solana") return "Solana extension (Phantom and other Solana wallets)";
|
|
89
|
+
if (kind === "tron") return "Tron extension (TronLink)";
|
|
90
|
+
|
|
91
|
+
return kind;
|
|
92
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import EthereumProvider from "@walletconnect/ethereum-provider";
|
|
2
|
+
|
|
3
|
+
import type { PubKey, Web3Provider } from "../types/web3-types";
|
|
4
|
+
import { Eip1193Provider, type Eip1193Like } from "./eip1193.provider";
|
|
5
|
+
|
|
6
|
+
export type WalletConnectEthereumConfig = {
|
|
7
|
+
projectId: string;
|
|
8
|
+
chains?: number[];
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export class WalletConnectEthereumProvider implements Web3Provider {
|
|
12
|
+
readonly id = "walletconnect";
|
|
13
|
+
|
|
14
|
+
private constructor(private inner: Eip1193Provider) {}
|
|
15
|
+
|
|
16
|
+
static async create(
|
|
17
|
+
config: WalletConnectEthereumConfig,
|
|
18
|
+
onAccountChange?: (pubKey: PubKey) => void,
|
|
19
|
+
) {
|
|
20
|
+
const wc = await EthereumProvider.init({
|
|
21
|
+
projectId: config.projectId,
|
|
22
|
+
chains: config.chains ?? [1],
|
|
23
|
+
optionalChains: [137, 10, 42161],
|
|
24
|
+
showQrModal: true,
|
|
25
|
+
metadata: {
|
|
26
|
+
name: document.title || "cruzo-web3",
|
|
27
|
+
description: "cruzo-web3 wallet signing",
|
|
28
|
+
url: window.location.origin,
|
|
29
|
+
icons: [],
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
return new WalletConnectEthereumProvider(
|
|
34
|
+
Eip1193Provider.fromEthereum(wc as Eip1193Like, onAccountChange),
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
connect() {
|
|
39
|
+
return this.inner.connect();
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
disconnect() {
|
|
43
|
+
return this.inner.disconnect();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
signMessage(message: string | Uint8Array) {
|
|
47
|
+
return this.inner.signMessage(message);
|
|
48
|
+
}
|
|
49
|
+
}
|
package/lib/pub-key.ts
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { normalizeSecp256k1Signature } from "./crypto/ecdsa-signature";
|
|
2
|
+
import { decodeEncodedBytes } from "./crypto/decode-bytes";
|
|
3
|
+
import { Web3Error } from "./errors/web3-error";
|
|
4
|
+
import type { PubKey, PubKeyAlgorithm, PubKeyEncoding } from "./types/web3-types";
|
|
5
|
+
|
|
6
|
+
const ALGORITHMS = new Set<PubKeyAlgorithm>(["secp256k1", "Ed25519", "sr25519"]);
|
|
7
|
+
const ENCODINGS = new Set<PubKeyEncoding>(["hex", "base64", "base58"]);
|
|
8
|
+
|
|
9
|
+
const ALGORITHM_LIST = [...ALGORITHMS].join(", ");
|
|
10
|
+
const ENCODING_LIST = [...ENCODINGS].join(", ");
|
|
11
|
+
|
|
12
|
+
const ENCODING_RE: Record<PubKeyEncoding, RegExp> = {
|
|
13
|
+
hex: /^[0-9a-fA-F]+$/,
|
|
14
|
+
base64: /^[A-Za-z0-9+/]+={0,2}$/,
|
|
15
|
+
base58: /^[1-9A-HJ-NP-Za-km-z]+$/,
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
type ByteCheck = (bytes: Uint8Array) => string | null;
|
|
19
|
+
|
|
20
|
+
const PUBLIC_KEY_CHECKS: Record<PubKeyAlgorithm, ByteCheck> = {
|
|
21
|
+
Ed25519: (bytes) =>
|
|
22
|
+
bytes.length === 32 ? null : `Ed25519 public key must be 32 bytes, got ${bytes.length}`,
|
|
23
|
+
secp256k1: (bytes) =>
|
|
24
|
+
isSecp256k1PublicKey(bytes)
|
|
25
|
+
? null
|
|
26
|
+
: "secp256k1 public key must be 33-byte compressed or 65-byte uncompressed",
|
|
27
|
+
sr25519: () => "sr25519 public key verification is not supported yet",
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const SIGNATURE_CHECKS: Record<PubKeyAlgorithm, ByteCheck> = {
|
|
31
|
+
Ed25519: (bytes) =>
|
|
32
|
+
bytes.length === 64 ? null : `Ed25519 signature must be 64 bytes, got ${bytes.length}`,
|
|
33
|
+
secp256k1: (bytes) =>
|
|
34
|
+
normalizeSecp256k1Signature(bytes)
|
|
35
|
+
? null
|
|
36
|
+
: "secp256k1 signature must be 64/65-byte raw or DER encoded",
|
|
37
|
+
sr25519: () => "sr25519 signature verification is not supported yet",
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
function isNonEmptyString(value: unknown): value is string {
|
|
41
|
+
return typeof value === "string" && value.length > 0;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function isSecp256k1PublicKey(bytes: Uint8Array) {
|
|
45
|
+
const compressed = bytes.length === 33 && (bytes[0] === 2 || bytes[0] === 3);
|
|
46
|
+
const uncompressed = bytes.length === 65 && bytes[0] === 4;
|
|
47
|
+
return compressed || uncompressed;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function readEncoding(encoding: string): PubKeyEncoding {
|
|
51
|
+
if (!ENCODINGS.has(encoding as PubKeyEncoding)) {
|
|
52
|
+
throw Web3Error.invalidPubKey(`Encoding must be one of: ${ENCODING_LIST}`);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return encoding as PubKeyEncoding;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function isValidEncodedValue(value: string, encoding: PubKeyEncoding) {
|
|
59
|
+
return isNonEmptyString(value) && ENCODING_RE[encoding].test(value);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function isPubKey(value: unknown): value is PubKey {
|
|
63
|
+
if (!value || typeof value !== "object") return false;
|
|
64
|
+
|
|
65
|
+
const pubKey = value as PubKey;
|
|
66
|
+
|
|
67
|
+
return (
|
|
68
|
+
ALGORITHMS.has(pubKey.type) &&
|
|
69
|
+
isNonEmptyString(pubKey.value) &&
|
|
70
|
+
ENCODINGS.has(pubKey.encoding)
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export function isValidPubKeyValue(value: string, encoding: PubKeyEncoding) {
|
|
75
|
+
return isValidEncodedValue(value, encoding);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function isValidPubKey(pubKey: PubKey) {
|
|
79
|
+
return isPubKey(pubKey) && isValidPubKeyValue(pubKey.value, pubKey.encoding);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export function parsePubKey(value: unknown): PubKey {
|
|
83
|
+
if (!value || typeof value !== "object") {
|
|
84
|
+
throw Web3Error.invalidPubKey("PubKey must be an object");
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const pubKey = value as PubKey;
|
|
88
|
+
|
|
89
|
+
if (!ALGORITHMS.has(pubKey.type)) {
|
|
90
|
+
throw Web3Error.invalidPubKey(`PubKey.type must be one of: ${ALGORITHM_LIST}`);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (!isNonEmptyString(pubKey.value)) {
|
|
94
|
+
throw Web3Error.invalidPubKey("PubKey.value must be a non-empty string");
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
readEncoding(pubKey.encoding);
|
|
98
|
+
|
|
99
|
+
if (!isValidEncodedValue(pubKey.value, pubKey.encoding)) {
|
|
100
|
+
throw Web3Error.invalidPubKey(`PubKey.value is not valid ${pubKey.encoding}`);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return {
|
|
104
|
+
type: pubKey.type,
|
|
105
|
+
value: pubKey.value,
|
|
106
|
+
encoding: pubKey.encoding,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export function decodePubKeyBytes(pubKey: PubKey) {
|
|
111
|
+
const key = parsePubKey(pubKey);
|
|
112
|
+
const bytes = decodeEncodedBytes(key.value, key.encoding);
|
|
113
|
+
|
|
114
|
+
if (!bytes) {
|
|
115
|
+
throw Web3Error.invalidPubKey(`Cannot decode PubKey.value as ${key.encoding}`);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
assertPublicKeyBytes(key.type, bytes);
|
|
119
|
+
return bytes;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export function decodeSignatureBytes(signature: string, encoding: PubKeyEncoding) {
|
|
123
|
+
if (!isValidEncodedValue(signature, encoding)) {
|
|
124
|
+
throw Web3Error.invalidSignature(`Signature is not valid ${encoding}`);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const bytes = decodeEncodedBytes(signature, encoding);
|
|
128
|
+
|
|
129
|
+
if (!bytes) {
|
|
130
|
+
throw Web3Error.invalidSignature(`Cannot decode signature as ${encoding}`);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return bytes;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export function assertPublicKeyBytes(type: PubKeyAlgorithm, bytes: Uint8Array) {
|
|
137
|
+
const message = PUBLIC_KEY_CHECKS[type](bytes);
|
|
138
|
+
if (message) throw Web3Error.invalidPubKey(message);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export function assertSignatureBytes(type: PubKeyAlgorithm, bytes: Uint8Array) {
|
|
142
|
+
const message = SIGNATURE_CHECKS[type](bytes);
|
|
143
|
+
if (message) throw Web3Error.invalidSignature(message);
|
|
144
|
+
}
|