@casper-ecosystem/casper-eip-712
v1.0.1
Published
EIP-712 typed data hashing and verification for Casper Network
Maintainers
Readme
@casper-ecosystem/casper-eip-712
TypeScript companion package for the Rust casper-eip-712 crate.
It provides EIP-712 typed data hashing plus ECDSA signature recovery for Casper-oriented flows, including support for Casper-specific domain fields when you supply explicit domain types.
Install
npm install @casper-ecosystem/casper-eip-712Quick start
import {
hashTypedData,
recoverTypedDataSigner,
verifySignature,
PermitTypes,
type PermitMessage,
} from "@casper-ecosystem/casper-eip-712";
const domain = {
name: "My Token",
version: "1",
chainId: 1,
verifyingContract: "0x1111111111111111111111111111111111111111",
};
const message: PermitMessage = {
owner: "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
spender: "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
value: "0x01",
nonce: "0x00",
deadline: "0xffff",
};
const signature = new Uint8Array(65); // Illustrative placeholder only; use a real 65-byte signature in production.
const digest = hashTypedData(domain, PermitTypes, "Permit", message);
const signer = recoverTypedDataSigner(domain, PermitTypes, "Permit", message, signature);
const isValid = verifySignature(digest, signature, "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");Casper-specific domains
If your domain uses Casper-specific fields such as chain_name or contract_package_hash, pass explicit domainTypes so the package knows the intended domain schema.
import { hashTypedData } from "@casper-ecosystem/casper-eip-712";
const domain = {
name: "CSPR",
version: "1",
chain_name: "casper-test",
contract_package_hash:
"0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
};
const digest = hashTypedData(domain, types, "Permit", message, {
domainTypes: [
{ name: "name", type: "string" },
{ name: "version", type: "string" },
{ name: "chain_name", type: "string" },
{ name: "contract_package_hash", type: "bytes32" },
],
});Rust-mirroring convenience helpers
For callers that want the lower-level shape from the Rust crate, the package also exposes:
import {
buildDomain,
CASPER_DOMAIN_TYPES,
computeTypeHash,
encodeAddress,
encodeUint256,
hashTypedDataRaw,
} from "@casper-ecosystem/casper-eip-712";
const domain = buildDomain(
"CasperToken",
"1",
"casper-test",
"0x7777777777777777777777777777777777777777777777777777777777777777",
);
const typeHash = computeTypeHash(
"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)",
);
const encodedStruct = new Uint8Array(32 * 5);
encodedStruct.set(encodeAddress("0x2222222222222222222222222222222222222222"), 0);
encodedStruct.set(encodeAddress("0x3333333333333333333333333333333333333333"), 32);
encodedStruct.set(encodeUint256(1n), 64);
encodedStruct.set(encodeUint256(0n), 96);
encodedStruct.set(encodeUint256(999999n), 128);
const digest = hashTypedDataRaw(domain, typeHash, encodedStruct, {
domainTypes: CASPER_DOMAIN_TYPES,
});API surface
buildDomain(name, version, chainName, contractPackageHash)hashDomainSeparator(domain, domainTypes?)hashStruct(primaryType, types, message)hashTypedData(domain, types, primaryType, message, options?)hashTypedDataRaw(domain, typeHash, encodedStruct, options?)computeTypeHash(typeString)recoverAddress(digest, signature)recoverTypedDataSigner(domain, types, primaryType, message, signature, options?)verifySignature(digest, signature, expectedAddress)- Encoding helpers:
encodeAddress,encodeUint256,encodeUint64,encodeBytes32,encodeBytes,encodeString,encodeBool,encodeField - Domain helpers:
CASPER_DOMAIN_TYPES,buildDomainTypeString - Prebuilt message types:
PermitTypes,ApprovalTypes,TransferTypes
Development
npm test
npm run buildCross-language parity is covered by test vectors in ../tests/vectors.json.
