UNPKG

@atomiqlabs/chain-starknet

Version:

Starknet specific base implementation

91 lines (80 loc) 3.27 kB
import {Buffer} from "buffer"; import {StarknetModule} from "../StarknetModule"; import {StarknetSigner} from "../../wallet/StarknetSigner"; import { Account, cairo, shortString, stark, StarknetDomain, StarknetType, TypedData } from "starknet"; import {StarknetChainInterface} from "../StarknetChainInterface"; import {toHex} from "../../../utils/Utils"; import {sha256} from "@noble/hashes/sha2"; const StarknetDomain = [ { name: 'name', type: 'shortstring' }, { name: 'version', type: 'shortstring' }, { name: 'chainId', type: 'shortstring' }, { name: 'revision', type: 'shortstring' }, ]; const DataHash = [ { name: 'Data hash', type: 'u256' } ]; export class StarknetSignatures extends StarknetModule { private readonly domain: StarknetDomain; constructor(root: StarknetChainInterface, domainName: string = "atomiq.exchange") { super(root); this.domain = { name: domainName, version: '1', chainId: shortString.decodeShortString(root.starknetChainId), revision: '1' }; } public getTypedMessage(type: StarknetType[], typeName: string, message: object): TypedData { return { types: { StarknetDomain, [typeName]: type, }, primaryType: typeName, domain: this.domain, message }; } public async signTypedMessage(signer: StarknetSigner, type: StarknetType[], typeName: string, message: object): Promise<string> { const signature = await signer.account.signMessage(this.getTypedMessage(type, typeName, message)); return JSON.stringify(stark.formatSignature(signature)); } public async isValidSignature(signature: string, address: string, type: StarknetType[], typeName: string, message: object) { return new Account(this.provider, address, null).verifyMessage( this.getTypedMessage(type, typeName, message), JSON.parse(signature) ) } /////////////////// //// Data signatures /** * Produces a signature over the sha256 of a specified data Buffer, only works with providers which * expose their private key (i.e. backend based, not browser wallet based) * * @param signer * @param data data to sign */ public getDataSignature(signer: StarknetSigner, data: Buffer): Promise<string> { const buff = Buffer.from(sha256(data)); return this.signTypedMessage(signer, DataHash, 'DataHash', {"Data hash": cairo.uint256(toHex(buff))}); } /** * Checks whether a signature is a valid signature produced by the account over a data message (computes * sha256 hash of the message) * * @param data signed data * @param signature data signature * @param address public key of the signer */ public isValidDataSignature(data: Buffer, signature: string, address: string): Promise<boolean> { const buff = Buffer.from(sha256(data)); return this.isValidSignature(signature, address, DataHash, 'DataHash', {"Data hash": cairo.uint256(toHex(buff))}); } }