UNPKG

check-ethereum-scanner

Version:

Safety checks for new Ethereum tokens

84 lines (74 loc) 3.02 kB
const F = require("forall"); const A = require("./array"); const B = require("./bytes"); const Account = require("./account"); F.Bytes = F(F.Type, { form: "a JavaScript String starting with a `0x`, followed by an even number of low-case hex chars (i.e., `0123456789abcdef`)", rand: () => "0x" + A.generate((Math.random() * 16 | 0) * 2, () => (Math.random() * 16 | 0).toString(16)).join(""), test: value => typeof value === "string" && /^0x([0-9a-f][0-9a-f])*$/.test(value), }).__name("Bytes").__desc("any arbitrary data"); F.NBytes = bytes => F(F.Type, { form: "a JavaScript String starting with a `0x`, followed by " + (bytes * 2) + " low-case hex chars (i.e., `0123456789abcdef`)", test: value => F.Bytes.test(value) && value.length === (bytes * 2 + 2), rand: () => "0x" + A.generate(bytes * 2, () => (Math.random() * 16 | 0).toString(16)).join("") }) .__name("NBytes(" + bytes + ")") .__desc("any arbitrary data of exactly " + bytes + "-byte" + (bytes > 1 ? "s" : "")); F.Nat = F(F.Type, { form: "a JavaScript String starting with a `0x`, followed by at least one low-case hex char different from 0, followed by any number of low-case hex chars (i.e., `0123456789abcdef`)", test: value => typeof value === "string" && /^0x[1-9a-f]([0-9a-f])*$/.test(value), rand: () => "0x" + (Math.random() * Math.pow(2,50) | 0).toString(16) }) .__name("Nat") .__desc("an arbitrarily long non-negative integer number"); F.Address = F(F.Type, { form: "a JavaScript String starting with a `0x`, followed by 40 hex chars (i.e., `0123456789abcdefABCDEF`), with the nth hex being uppercase iff the nth hex of the keccak256 of the lowercase address in ASCII is > 7", test: address => /^(0x)?[0-9a-f]{40}$/i.test(address) && Account.toChecksum(address.toLowerCase()) === address, rand: () => F.Account.rand().address }) .__name("Address") .__desc("an Ethereum public address"); F.Hash = F(F.Type, { form: F.NBytes(32).form, test: F.NBytes(32).test, rand: F.NBytes(32).rand }) .__name("Hash") .__desc("a Keccak-256 hash"); F.PrivateKey = F(F.Type, { form: F.NBytes(32).form, test: F.NBytes(32).test, rand: F.NBytes(32).rand }) .__name("PrivateKey") .__desc("an Ethereum private key"); F.Account = (() => { const base = F.Struct({ address: F.Address, privateKey: F.PrivateKey, }); return F(F.Type, { form: base.form, test: base.test, rand: () => Account.create("") }); })() .__name("Account") .__desc("an Ethereum account"); F.BytesTree = F(F.Type, { form: "either " + F.Bytes.form + ", or a tree of nested JavaScript Arrays of BytesTrees", test: value => F.Bytes.test(value) || value instanceof Array && value.reduce((r,v) => F.BytesTree.test(v) && r, true), rand: () => { let list = []; while (Math.random() < 0.8) { if (Math.random() < 0.8) list.push(F.Bytes.rand()); else list.push(F.BytesTree.rand()); } return list; } }) .__name("BytesTree") .__desc("a tree of arbitrary binary data"); module.exports = F;