Last active
August 19, 2024 11:54
-
-
Save codeWhizperer/930a4a72de4d50b21a96407748bfa2e2 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { Account, RpcProvider, Signature, WeierstrassSignatureType, ec, encode, typedData, Signer as StarknetSigner } from "starknet"; | |
| import type { Signer } from "../index"; | |
| import { SignatureConfig, SIG_CONFIG } from "../../constants"; | |
| import { get_domain } from "./StarknetSigner"; | |
| export default class InjectedStarknetSigner implements Signer { | |
| protected signer: Account; | |
| public publicKey: Buffer; | |
| public static address: string; | |
| private static privateKey: string; | |
| public static provider: RpcProvider; | |
| public static chainId: string; | |
| readonly ownerLength: number = SIG_CONFIG[SignatureConfig.STARKNET].pubLength; | |
| readonly signatureLength: number = SIG_CONFIG[SignatureConfig.STARKNET].sigLength; | |
| readonly signatureType: number = SignatureConfig.STARKNET; | |
| // Constructor to set static properties | |
| constructor(provider: RpcProvider, address: string, pKey: string) { | |
| InjectedStarknetSigner.provider = provider; | |
| InjectedStarknetSigner.address = address; | |
| InjectedStarknetSigner.privateKey = pKey; | |
| this.signer = new Account(provider, address, pKey); | |
| } | |
| public async init() { | |
| try { | |
| const signer = new StarknetSigner(InjectedStarknetSigner.privateKey); | |
| const pub_key = await signer.getPubKey(); | |
| let hexKey = pub_key.startsWith("0x") ? pub_key.slice(2) : pub_key; | |
| this.publicKey = Buffer.from(hexKey, "hex"); | |
| InjectedStarknetSigner.chainId = await InjectedStarknetSigner.provider.getChainId(); | |
| } catch (error) { | |
| console.error("Error setting public key or chain ID:", error); | |
| } | |
| } | |
| async sign(message: Uint8Array, _opts?: any): Promise<Uint8Array> { | |
| if (!this.signer.signMessage) throw new Error("Selected signer does not support message signing"); | |
| let message_to_string = convertToFelt252(message); | |
| let TypedDataMessage = get_domain({ chainId: InjectedStarknetSigner.chainId, message: message_to_string }); | |
| let signature: Signature = (await this.signer.signMessage(TypedDataMessage.typemessage)) as WeierstrassSignatureType; | |
| const r = BigInt(signature.r).toString(16).padStart(64, "0"); | |
| const s = BigInt(signature.s).toString(16).padStart(64, "0"); | |
| // @ts-ignore | |
| const recovery = signature.recovery.toString(16).padStart(2, "0"); | |
| const rArray = Uint8Array.from(Buffer.from(r, "hex")); | |
| const sArray = Uint8Array.from(Buffer.from(s, "hex")); | |
| const recoveryArray = Uint8Array.from(Buffer.from(recovery, "hex")); | |
| const result = new Uint8Array(rArray.length + sArray.length + recoveryArray.length); | |
| result.set(rArray); | |
| result.set(sArray, rArray.length); | |
| result.set(recoveryArray, rArray.length + sArray.length); | |
| return result; | |
| } | |
| static async verify(_pk: string | Buffer, message: Uint8Array, _signature: Uint8Array, _opts?: any): Promise<boolean> { | |
| let message_to_string = convertToFelt252(message); | |
| let TypedDataMessage = get_domain({ chainId: InjectedStarknetSigner.chainId, message: message_to_string }); | |
| const fullPubKey = encode.addHexPrefix( | |
| encode.buf2hex(ec.starkCurve.getPublicKey("0x005d5c250b5c181684ae6d8ebfa0faeac3ad0c6f31a6c2f102a2fffddba00a05", false)), | |
| ); | |
| const msgHash = typedData.getMessageHash(TypedDataMessage.typemessage, InjectedStarknetSigner.address); | |
| return ec.starkCurve.verify(_signature.slice(0, -1), msgHash, fullPubKey); | |
| } | |
| } | |
| // Utility function to convert Uint8Array to felt252 | |
| function convertToFelt252(data: Uint8Array): bigint[] { | |
| const felt252Array: bigint[] = []; | |
| const felt252Size = 31; | |
| for (let i = 0; i < data.length; i += felt252Size) { | |
| let value = BigInt(0); | |
| for (let j = 0; j < felt252Size && i + j < data.length; j++) { | |
| value = (value << BigInt(8)) | BigInt(data[i + j]); | |
| } | |
| felt252Array.push(value); | |
| } | |
| return felt252Array; | |
| } | |
| //////get_domain | |
| import { TypedData, TypedDataRevision} from "starknet" | |
| interface Itype { | |
| chainId: string | number, | |
| message:bigint[] | |
| } | |
| export const get_domain = ({ | |
| chainId, | |
| message, | |
| }: Itype): { typemessage: TypedData } => { | |
| const typemessage: TypedData = { | |
| domain: { | |
| name: "Arbundle", | |
| chainId: chainId, | |
| version: "1.0.2", | |
| revision: TypedDataRevision.ACTIVE, | |
| }, | |
| message: { | |
| message, | |
| }, | |
| primaryType: "Message", | |
| types: { | |
| Message: [{ name: "message", type: "felt*" }], | |
| StarknetDomain: [ | |
| { name: "name", type: "string" }, | |
| { name: "chainId", type: "felt" }, | |
| { name: "version", type: "string" }, | |
| ], | |
| }, | |
| }; | |
| return { | |
| typemessage, | |
| }; | |
| }; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment