micro-eth-signer
Advanced tools
Comparing version 0.10.0 to 0.11.0
@@ -123,2 +123,49 @@ "use strict"; | ||
assertType(abi.events(TRANSFER_EVENT)); | ||
// Typed data | ||
const types = { | ||
Person: [ | ||
{ name: 'name', type: 'string' }, | ||
{ name: 'wallet', type: 'address' }, | ||
], | ||
Mail: [ | ||
{ name: 'from', type: 'Person' }, | ||
{ name: 'to', type: 'Person' }, | ||
{ name: 'contents', type: 'string' }, | ||
], | ||
Group: [ | ||
{ name: 'members', type: 'Person[]' }, | ||
{ name: 'owner', type: 'Person' }, | ||
], | ||
Complex0: [ | ||
{ name: 'data', type: 'string[][]' }, // Complex array type | ||
{ name: 'info', type: 'Mail' }, | ||
], | ||
Complex1: [ | ||
{ name: 'data', type: 'string[][][]' }, // Complex array type | ||
{ name: 'info', type: 'Mail' }, | ||
], | ||
Complex: [ | ||
{ name: 'data', type: 'string[][3][]' }, // Complex array type | ||
{ name: 'info', type: 'Mail' }, | ||
], | ||
}; | ||
assertType(1); | ||
assertType(1); | ||
assertType(1); | ||
assertType(1); | ||
assertType(1); | ||
assertType(1); | ||
const recursiveTypes = { | ||
Node: [ | ||
{ name: 'value', type: 'string' }, | ||
{ name: 'children', type: 'Node[]' }, | ||
], | ||
}; | ||
assertType(1); | ||
// const e = typed.encoder(types); | ||
// e.encodeData('Person', { name: 'test', wallet: 'x' }); | ||
// e.sign({ primaryType: 'Person', message: { name: 'test', wallet: 'x' }, domain: {} }, ''); | ||
// e.encodeData('Person', { name: 'test', wallet: 1n }); // should fail | ||
// e.sign({ primaryType: 'Person', message: {name: 'test'}, domain: {} }, ''); // should fail | ||
// e.sign({ primaryType: 'Person', message: {name: 'test', wallet: '', s: 3}, domain: {} }, ''); // should fail | ||
//# sourceMappingURL=_type_test.js.map |
import * as P from 'micro-packed'; | ||
import { Web3Provider } from '../utils.js'; | ||
import { IWeb3Provider } from '../utils.js'; | ||
type Writable<T> = T extends {} ? { | ||
@@ -26,8 +26,2 @@ -readonly [P in keyof T]: Writable<T[P]>; | ||
type ByteType = `bytes${ByteIdxType}`; | ||
type DigitsType = '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'; | ||
type ThrityDigits = DigitsType | `${'1' | '2' | '3'}${'0' | DigitsType}`; | ||
type TwoDigits = DigitsType | `${DigitsType}${'0' | DigitsType}`; | ||
type ThreeDigits = TwoDigits | `${TwoDigits}${'0' | DigitsType}`; | ||
type ArrType<T extends string> = `${T}[${'' | ThreeDigits}]`; | ||
type Arr2dType<T extends string> = `${T}[${'' | ThrityDigits}][${'' | ThrityDigits}]`; | ||
export type MapTuple<T> = T extends ArrLike<Component<string> & { | ||
@@ -40,3 +34,4 @@ name: string; | ||
} : unknown; | ||
export type MapType<T extends BaseComponent> = T extends Component<'string'> ? string : T extends Component<ArrType<'string'>> ? string[] : T extends Component<Arr2dType<'string'>> ? string[][] : T extends Component<'address'> ? string : T extends Component<ArrType<'address'>> ? string[] : T extends Component<Arr2dType<'address'>> ? string[][] : T extends Component<'bool'> ? boolean : T extends Component<ArrType<'bool'>> ? boolean[] : T extends Component<Arr2dType<'bool'>> ? boolean[][] : T extends Component<NumberType> ? bigint : T extends Component<ArrType<NumberType>> ? bigint[] : T extends Component<Arr2dType<NumberType>> ? bigint[][] : T extends Component<ByteType> ? Uint8Array : T extends Component<ArrType<ByteType>> ? Uint8Array[] : T extends Component<Arr2dType<ByteType>> ? Uint8Array[][] : T extends Tuple<Array<Component<string>>> ? MapTuple<T['components']> : unknown; | ||
export type GetType<T extends string> = T extends `${infer Base}[]${infer Rest}` ? GetType<`${Base}${Rest}`>[] : T extends `${infer Base}[${number}]${infer Rest}` ? GetType<`${Base}${Rest}`>[] : T extends 'address' ? string : T extends 'string' ? string : T extends 'bool' ? boolean : T extends NumberType ? bigint : T extends ByteType ? Uint8Array : unknown; | ||
export type MapType<T extends BaseComponent> = T extends Tuple<Array<Component<string>>> ? MapTuple<T['components']> : T extends Component<infer Type> ? GetType<Type> : unknown; | ||
export type UnmapType<T> = T extends MapType<infer U> ? U : never; | ||
@@ -99,7 +94,7 @@ export declare function mapComponent<T extends BaseComponent>(c: T): P.CoderType<MapType<Writable<T>>>; | ||
}> ? { | ||
[K in F[number] as K['name']]: N extends Web3Provider ? ContractMethodNet<K> : ContractMethod<K>; | ||
[K in F[number] as K['name']]: N extends IWeb3Provider ? ContractMethodNet<K> : ContractMethod<K>; | ||
} : never; | ||
export declare function evSigHash(o: FnArg): string; | ||
export declare function fnSigHash(o: FnArg): string; | ||
export declare function createContract<T extends ArrLike<FnArg>>(abi: T, net: Web3Provider, contract?: string): ContractType<Writable<T>, Web3Provider>; | ||
export declare function createContract<T extends ArrLike<FnArg>>(abi: T, net: IWeb3Provider, contract?: string): ContractType<Writable<T>, IWeb3Provider>; | ||
export declare function createContract<T extends ArrLike<FnArg>>(abi: T, net?: undefined, contract?: string): ContractType<Writable<T>, undefined>; | ||
@@ -106,0 +101,0 @@ export type EventType = NamedComponent<'event'> & { |
@@ -121,2 +121,49 @@ import * as abi from './abi/decoder.js'; | ||
assertType(abi.events(TRANSFER_EVENT)); | ||
// Typed data | ||
const types = { | ||
Person: [ | ||
{ name: 'name', type: 'string' }, | ||
{ name: 'wallet', type: 'address' }, | ||
], | ||
Mail: [ | ||
{ name: 'from', type: 'Person' }, | ||
{ name: 'to', type: 'Person' }, | ||
{ name: 'contents', type: 'string' }, | ||
], | ||
Group: [ | ||
{ name: 'members', type: 'Person[]' }, | ||
{ name: 'owner', type: 'Person' }, | ||
], | ||
Complex0: [ | ||
{ name: 'data', type: 'string[][]' }, // Complex array type | ||
{ name: 'info', type: 'Mail' }, | ||
], | ||
Complex1: [ | ||
{ name: 'data', type: 'string[][][]' }, // Complex array type | ||
{ name: 'info', type: 'Mail' }, | ||
], | ||
Complex: [ | ||
{ name: 'data', type: 'string[][3][]' }, // Complex array type | ||
{ name: 'info', type: 'Mail' }, | ||
], | ||
}; | ||
assertType(1); | ||
assertType(1); | ||
assertType(1); | ||
assertType(1); | ||
assertType(1); | ||
assertType(1); | ||
const recursiveTypes = { | ||
Node: [ | ||
{ name: 'value', type: 'string' }, | ||
{ name: 'children', type: 'Node[]' }, | ||
], | ||
}; | ||
assertType(1); | ||
// const e = typed.encoder(types); | ||
// e.encodeData('Person', { name: 'test', wallet: 'x' }); | ||
// e.sign({ primaryType: 'Person', message: { name: 'test', wallet: 'x' }, domain: {} }, ''); | ||
// e.encodeData('Person', { name: 'test', wallet: 1n }); // should fail | ||
// e.sign({ primaryType: 'Person', message: {name: 'test'}, domain: {} }, ''); // should fail | ||
// e.sign({ primaryType: 'Person', message: {name: 'test', wallet: '', s: 3}, domain: {} }, ''); // should fail | ||
//# sourceMappingURL=_type_test.js.map |
import * as P from 'micro-packed'; | ||
import { Web3Provider } from '../utils.js'; | ||
import { IWeb3Provider } from '../utils.js'; | ||
type Writable<T> = T extends {} ? { | ||
@@ -26,8 +26,2 @@ -readonly [P in keyof T]: Writable<T[P]>; | ||
type ByteType = `bytes${ByteIdxType}`; | ||
type DigitsType = '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'; | ||
type ThrityDigits = DigitsType | `${'1' | '2' | '3'}${'0' | DigitsType}`; | ||
type TwoDigits = DigitsType | `${DigitsType}${'0' | DigitsType}`; | ||
type ThreeDigits = TwoDigits | `${TwoDigits}${'0' | DigitsType}`; | ||
type ArrType<T extends string> = `${T}[${'' | ThreeDigits}]`; | ||
type Arr2dType<T extends string> = `${T}[${'' | ThrityDigits}][${'' | ThrityDigits}]`; | ||
export type MapTuple<T> = T extends ArrLike<Component<string> & { | ||
@@ -40,3 +34,4 @@ name: string; | ||
} : unknown; | ||
export type MapType<T extends BaseComponent> = T extends Component<'string'> ? string : T extends Component<ArrType<'string'>> ? string[] : T extends Component<Arr2dType<'string'>> ? string[][] : T extends Component<'address'> ? string : T extends Component<ArrType<'address'>> ? string[] : T extends Component<Arr2dType<'address'>> ? string[][] : T extends Component<'bool'> ? boolean : T extends Component<ArrType<'bool'>> ? boolean[] : T extends Component<Arr2dType<'bool'>> ? boolean[][] : T extends Component<NumberType> ? bigint : T extends Component<ArrType<NumberType>> ? bigint[] : T extends Component<Arr2dType<NumberType>> ? bigint[][] : T extends Component<ByteType> ? Uint8Array : T extends Component<ArrType<ByteType>> ? Uint8Array[] : T extends Component<Arr2dType<ByteType>> ? Uint8Array[][] : T extends Tuple<Array<Component<string>>> ? MapTuple<T['components']> : unknown; | ||
export type GetType<T extends string> = T extends `${infer Base}[]${infer Rest}` ? GetType<`${Base}${Rest}`>[] : T extends `${infer Base}[${number}]${infer Rest}` ? GetType<`${Base}${Rest}`>[] : T extends 'address' ? string : T extends 'string' ? string : T extends 'bool' ? boolean : T extends NumberType ? bigint : T extends ByteType ? Uint8Array : unknown; | ||
export type MapType<T extends BaseComponent> = T extends Tuple<Array<Component<string>>> ? MapTuple<T['components']> : T extends Component<infer Type> ? GetType<Type> : unknown; | ||
export type UnmapType<T> = T extends MapType<infer U> ? U : never; | ||
@@ -99,7 +94,7 @@ export declare function mapComponent<T extends BaseComponent>(c: T): P.CoderType<MapType<Writable<T>>>; | ||
}> ? { | ||
[K in F[number] as K['name']]: N extends Web3Provider ? ContractMethodNet<K> : ContractMethod<K>; | ||
[K in F[number] as K['name']]: N extends IWeb3Provider ? ContractMethodNet<K> : ContractMethod<K>; | ||
} : never; | ||
export declare function evSigHash(o: FnArg): string; | ||
export declare function fnSigHash(o: FnArg): string; | ||
export declare function createContract<T extends ArrLike<FnArg>>(abi: T, net: Web3Provider, contract?: string): ContractType<Writable<T>, Web3Provider>; | ||
export declare function createContract<T extends ArrLike<FnArg>>(abi: T, net: IWeb3Provider, contract?: string): ContractType<Writable<T>, IWeb3Provider>; | ||
export declare function createContract<T extends ArrLike<FnArg>>(abi: T, net?: undefined, contract?: string): ContractType<Writable<T>, undefined>; | ||
@@ -106,0 +101,0 @@ export type EventType = NamedComponent<'event'> & { |
@@ -1,2 +0,2 @@ | ||
import { Web3Provider, Web3CallArgs } from '../utils.js'; | ||
import { IWeb3Provider, Web3CallArgs } from '../utils.js'; | ||
import { TxVersions } from '../tx.js'; | ||
@@ -179,3 +179,3 @@ import { ContractInfo } from '../abi/index.js'; | ||
*/ | ||
export declare class ArchiveNodeProvider implements Web3Provider { | ||
export declare class Web3Provider implements IWeb3Provider { | ||
private rpc; | ||
@@ -182,0 +182,0 @@ constructor(rpc: JsonrpcInterface); |
@@ -168,3 +168,3 @@ import { hexToNumber, amounts } from '../utils.js'; | ||
*/ | ||
export class ArchiveNodeProvider { | ||
export class Web3Provider { | ||
constructor(rpc) { | ||
@@ -171,0 +171,0 @@ this.rpc = rpc; |
@@ -1,2 +0,2 @@ | ||
import { Web3Provider } from '../utils.js'; | ||
import { IWeb3Provider } from '../utils.js'; | ||
export declare const TOKENS: Record<string, { | ||
@@ -8,4 +8,4 @@ decimals: number; | ||
export default class Chainlink { | ||
readonly net: Web3Provider; | ||
constructor(net: Web3Provider); | ||
readonly net: IWeb3Provider; | ||
constructor(net: IWeb3Provider); | ||
price(contract: string, decimals: number): Promise<number>; | ||
@@ -12,0 +12,0 @@ coinPrice(symbol: string): Promise<number>; |
@@ -1,5 +0,5 @@ | ||
import { Web3Provider } from '../utils.js'; | ||
import { IWeb3Provider } from '../utils.js'; | ||
export declare function namehash(address: string): Uint8Array; | ||
export default class ENS { | ||
readonly net: Web3Provider; | ||
readonly net: IWeb3Provider; | ||
static ADDRESS_ZERO: string; | ||
@@ -39,3 +39,3 @@ static REGISTRY: string; | ||
}]; | ||
constructor(net: Web3Provider); | ||
constructor(net: IWeb3Provider); | ||
getResolver(name: string): Promise<string | undefined>; | ||
@@ -42,0 +42,0 @@ nameToAddress(name: string): Promise<string | undefined>; |
import Chainlink from './chainlink.js'; | ||
import ENS from './ens.js'; | ||
import { ArchiveNodeProvider, calcTransfersDiff } from './archive.js'; | ||
import { Web3Provider, calcTransfersDiff } from './archive.js'; | ||
import UniswapV2 from './uniswap-v2.js'; | ||
import UniswapV3 from './uniswap-v3.js'; | ||
export { ArchiveNodeProvider, calcTransfersDiff, Chainlink, ENS, UniswapV2, UniswapV3 }; | ||
export { Web3Provider, calcTransfersDiff, Chainlink, ENS, UniswapV2, UniswapV3 }; | ||
//# sourceMappingURL=index.d.ts.map |
import Chainlink from './chainlink.js'; | ||
import ENS from './ens.js'; | ||
import { ArchiveNodeProvider, calcTransfersDiff } from './archive.js'; | ||
import { Web3Provider, calcTransfersDiff } from './archive.js'; | ||
import UniswapV2 from './uniswap-v2.js'; | ||
import UniswapV3 from './uniswap-v3.js'; | ||
// There are many low level APIs inside which are not exported yet. | ||
export { ArchiveNodeProvider, calcTransfersDiff, Chainlink, ENS, UniswapV2, UniswapV3 }; | ||
export { Web3Provider, calcTransfersDiff, Chainlink, ENS, UniswapV2, UniswapV3 }; | ||
//# sourceMappingURL=index.js.map |
@@ -1,2 +0,2 @@ | ||
import { Web3Provider } from '../utils.js'; | ||
import { IWeb3Provider } from '../utils.js'; | ||
export type SwapOpt = { | ||
@@ -50,3 +50,3 @@ slippagePercent: number; | ||
export declare abstract class UniswapAbstract { | ||
net: Web3Provider; | ||
net: IWeb3Provider; | ||
abstract name: string; | ||
@@ -58,3 +58,3 @@ abstract contract: string; | ||
}): any; | ||
constructor(net: Web3Provider); | ||
constructor(net: IWeb3Provider); | ||
swap(fromCoin: 'eth' | Token, toCoin: 'eth' | Token, amount: string, opt?: SwapOpt): Promise<{ | ||
@@ -61,0 +61,0 @@ name: string; |
@@ -14,3 +14,3 @@ import { isBytes as _isBytes } from '@noble/hashes/utils'; | ||
}>; | ||
export type Web3Provider = { | ||
export type IWeb3Provider = { | ||
ethCall: (args: Web3CallArgs) => Promise<string>; | ||
@@ -41,3 +41,3 @@ estimateGas: (args: Web3CallArgs) => Promise<bigint>; | ||
export declare function hexToNumber(hex: string): bigint; | ||
export declare function isObject(item: unknown): item is object; | ||
export declare function isObject(item: unknown): item is Record<string, any>; | ||
export declare function astr(str: unknown): void; | ||
@@ -44,0 +44,0 @@ export declare function cloneDeep<T>(obj: T): T; |
@@ -1,2 +0,2 @@ | ||
import { Web3Provider, Web3CallArgs } from '../utils.js'; | ||
import { IWeb3Provider, Web3CallArgs } from '../utils.js'; | ||
import { TxVersions } from '../tx.js'; | ||
@@ -179,3 +179,3 @@ import { ContractInfo } from '../abi/index.js'; | ||
*/ | ||
export declare class ArchiveNodeProvider implements Web3Provider { | ||
export declare class Web3Provider implements IWeb3Provider { | ||
private rpc; | ||
@@ -182,0 +182,0 @@ constructor(rpc: JsonrpcInterface); |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.ArchiveNodeProvider = void 0; | ||
exports.Web3Provider = void 0; | ||
exports.calcTransfersDiff = calcTransfersDiff; | ||
@@ -172,3 +172,3 @@ const utils_js_1 = require("../utils.js"); | ||
*/ | ||
class ArchiveNodeProvider { | ||
class Web3Provider { | ||
constructor(rpc) { | ||
@@ -506,3 +506,3 @@ this.rpc = rpc; | ||
} | ||
exports.ArchiveNodeProvider = ArchiveNodeProvider; | ||
exports.Web3Provider = Web3Provider; | ||
/** | ||
@@ -509,0 +509,0 @@ * Calculates balances at specific point in time after tx. |
@@ -1,2 +0,2 @@ | ||
import { Web3Provider } from '../utils.js'; | ||
import { IWeb3Provider } from '../utils.js'; | ||
export declare const TOKENS: Record<string, { | ||
@@ -8,4 +8,4 @@ decimals: number; | ||
export default class Chainlink { | ||
readonly net: Web3Provider; | ||
constructor(net: Web3Provider); | ||
readonly net: IWeb3Provider; | ||
constructor(net: IWeb3Provider); | ||
price(contract: string, decimals: number): Promise<number>; | ||
@@ -12,0 +12,0 @@ coinPrice(symbol: string): Promise<number>; |
@@ -1,5 +0,5 @@ | ||
import { Web3Provider } from '../utils.js'; | ||
import { IWeb3Provider } from '../utils.js'; | ||
export declare function namehash(address: string): Uint8Array; | ||
export default class ENS { | ||
readonly net: Web3Provider; | ||
readonly net: IWeb3Provider; | ||
static ADDRESS_ZERO: string; | ||
@@ -39,3 +39,3 @@ static REGISTRY: string; | ||
}]; | ||
constructor(net: Web3Provider); | ||
constructor(net: IWeb3Provider); | ||
getResolver(name: string): Promise<string | undefined>; | ||
@@ -42,0 +42,0 @@ nameToAddress(name: string): Promise<string | undefined>; |
import Chainlink from './chainlink.js'; | ||
import ENS from './ens.js'; | ||
import { ArchiveNodeProvider, calcTransfersDiff } from './archive.js'; | ||
import { Web3Provider, calcTransfersDiff } from './archive.js'; | ||
import UniswapV2 from './uniswap-v2.js'; | ||
import UniswapV3 from './uniswap-v3.js'; | ||
export { ArchiveNodeProvider, calcTransfersDiff, Chainlink, ENS, UniswapV2, UniswapV3 }; | ||
export { Web3Provider, calcTransfersDiff, Chainlink, ENS, UniswapV2, UniswapV3 }; | ||
//# sourceMappingURL=index.d.ts.map |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.UniswapV3 = exports.UniswapV2 = exports.ENS = exports.Chainlink = exports.calcTransfersDiff = exports.ArchiveNodeProvider = void 0; | ||
exports.UniswapV3 = exports.UniswapV2 = exports.ENS = exports.Chainlink = exports.calcTransfersDiff = exports.Web3Provider = void 0; | ||
const chainlink_js_1 = require("./chainlink.js"); | ||
@@ -9,3 +9,3 @@ exports.Chainlink = chainlink_js_1.default; | ||
const archive_js_1 = require("./archive.js"); | ||
Object.defineProperty(exports, "ArchiveNodeProvider", { enumerable: true, get: function () { return archive_js_1.ArchiveNodeProvider; } }); | ||
Object.defineProperty(exports, "Web3Provider", { enumerable: true, get: function () { return archive_js_1.Web3Provider; } }); | ||
Object.defineProperty(exports, "calcTransfersDiff", { enumerable: true, get: function () { return archive_js_1.calcTransfersDiff; } }); | ||
@@ -12,0 +12,0 @@ const uniswap_v2_js_1 = require("./uniswap-v2.js"); |
@@ -1,2 +0,2 @@ | ||
import { Web3Provider } from '../utils.js'; | ||
import { IWeb3Provider } from '../utils.js'; | ||
export type SwapOpt = { | ||
@@ -50,3 +50,3 @@ slippagePercent: number; | ||
export declare abstract class UniswapAbstract { | ||
net: Web3Provider; | ||
net: IWeb3Provider; | ||
abstract name: string; | ||
@@ -58,3 +58,3 @@ abstract contract: string; | ||
}): any; | ||
constructor(net: Web3Provider); | ||
constructor(net: IWeb3Provider); | ||
swap(fromCoin: 'eth' | Token, toCoin: 'eth' | Token, amount: string, opt?: SwapOpt): Promise<{ | ||
@@ -61,0 +61,0 @@ name: string; |
{ | ||
"name": "micro-eth-signer", | ||
"version": "0.10.0", | ||
"version": "0.11.0", | ||
"description": "Minimal library for Ethereum transactions, addresses and smart contracts", | ||
@@ -19,8 +19,8 @@ "files": [ | ||
"dependencies": { | ||
"@noble/curves": "~1.4.0", | ||
"@noble/hashes": "~1.4.0", | ||
"@noble/curves": "~1.6.0", | ||
"@noble/hashes": "~1.5.0", | ||
"micro-packed": "~0.6.3" | ||
}, | ||
"devDependencies": { | ||
"@paulmillr/jsbt": "0.1.0", | ||
"@paulmillr/jsbt": "0.2.1", | ||
"micro-bmark": "0.3.1", | ||
@@ -49,2 +49,10 @@ "micro-ftch": "0.4.0", | ||
}, | ||
"./address": { | ||
"import": "./esm/address.js", | ||
"require": "./address.js" | ||
}, | ||
"./kzg": { | ||
"import": "./esm/kzg.js", | ||
"require": "./kzg.js" | ||
}, | ||
"./net": { | ||
@@ -66,2 +74,6 @@ "import": "./esm/net/index.js", | ||
}, | ||
"./typed-data": { | ||
"import": "./esm/typed-data.js", | ||
"require": "./typed-data.js" | ||
}, | ||
"./utils": { | ||
@@ -72,2 +84,3 @@ "import": "./esm/utils.js", | ||
}, | ||
"sideEffects": false, | ||
"keywords": [ | ||
@@ -92,6 +105,6 @@ "ethereum", | ||
"bench": "node benchmark/tx.js", | ||
"lint": "prettier --print-width 100 --single-quote --check src", | ||
"format": "prettier --print-width 100 --single-quote --write src", | ||
"lint": "prettier --check src", | ||
"format": "prettier --write src", | ||
"test": "node test/index.js" | ||
} | ||
} |
122
README.md
@@ -8,7 +8,7 @@ # micro-eth-signer | ||
- 🔍 Reliable: 150MB of test vectors from EIPs, ethers and viem | ||
- ✍️ Create, sign and decode transactions using human-readable hints | ||
- 🌍 Fetch balances and history from an archive node | ||
- 🆎 Call smart contracts: Chainlink and Uniswap APIs are included | ||
- 🦺 Typescript-friendly ABI, RLP and SSZ decoding | ||
- 🪶 1200 lines for core functionality | ||
- ✍️ Transactions: create, sign, decode with human-friendly hints | ||
- 🆎 Execute contracts in JS: includes Chainlink and Uniswap APIs | ||
- 🦺 Typescript-friendly: ABI parsing, RLP, SSZ, KZG proof generation & verification | ||
- 🌍 Archive-node-friendly: fetch balances & history | ||
- 🪶 Lightweight: 1200 lines for core functionality | ||
@@ -44,4 +44,5 @@ Check out article [ZSTs, ABIs, stolen keys and broken legs](https://github.com/paulmillr/micro-eth-signer/discussions/20) about caveats of secure ABI parsing found during development of the library. | ||
- Utilities | ||
- [KZG EIP-4844 proofs](#kzg-eip-4844-proofs) | ||
- [Send whole account balance](#send-whole-account-balance) | ||
- [Sign and verify messages](#sign-and-verify-messages) | ||
- [Sign and verify messages with EIP-191 and EIP-712](#sign-and-verify-messages-with-eip-191-and-eip-712) | ||
- [Security](#security) | ||
@@ -110,8 +111,8 @@ - [Performance](#performance) | ||
Most APIs (chainlink, uniswap) expect instance of ArchiveNodeProvider. | ||
Most APIs (chainlink, uniswap) expect instance of Web3Provider. | ||
The call stack would look like this: | ||
- `Chainlink` => `ArchiveNodeProvider` => `jsonrpc` => `fetch` | ||
- `Chainlink` => `Web3Provider` => `jsonrpc` => `fetch` | ||
To initialize ArchiveNodeProvider, do the following: | ||
To initialize Web3Provider, do the following: | ||
@@ -121,9 +122,9 @@ ```js | ||
import { jsonrpc } from 'micro-ftch'; | ||
import { ArchiveNodeProvider } from 'micro-eth-signer/net'; | ||
import { Web3Provider } from 'micro-eth-signer/net'; | ||
const RPC_URL = 'http://localhost:8545'; | ||
const prov = new ArchiveNodeProvider(jsonrpc(fetch, RPC_URL)); | ||
const prov = new Web3Provider(jsonrpc(fetch, RPC_URL)); | ||
// Example using mewapi RPC | ||
const RPC_URL_2 = 'https://nodes.mewapi.io/rpc/eth'; | ||
const prov2 = new ArchiveNodeProvider( | ||
const prov2 = new Web3Provider( | ||
jsonrpc(fetch, RPC_URL_2, { Origin: 'https://www.myetherwallet.com' }) | ||
@@ -141,3 +142,3 @@ ); | ||
// Other methods of ArchiveNodeProvider: | ||
// Other methods of Web3Provider: | ||
// blockInfo(block: number): Promise<BlockInfo>; // {baseFeePerGas, hash, timestamp...} | ||
@@ -366,12 +367,65 @@ // height(): Promise<number>; | ||
### Sign and verify messages | ||
### Sign and verify messages with EIP-191 and EIP-712 | ||
EIP-712 is not supported yet. | ||
We support EIP-191 and EIP-712. | ||
```ts | ||
import { addr, messenger } from 'micro-eth-signer'; | ||
const rand = addr.random(); | ||
const msg = 'noble'; | ||
const sig = messenger.sign(msg, rand.privateKey); | ||
const isValid = messenger.verify(sig, msg, address); | ||
import * as typed from 'micro-eth-signer/typed-data'; | ||
// EIP-191 | ||
const sig = typed.personal.sign(message, privateKey); | ||
typed.personal.verify(sig, message, address); | ||
typed.personal.recoverPublicKey(sig, message); | ||
// EIP-712 | ||
const typedData = { | ||
types: { | ||
EIP712Domain: [ | ||
{ name: 'name', type: 'string' }, | ||
{ name: 'version', type: 'string' }, | ||
{ name: 'chainId', type: 'uint256' }, | ||
{ name: 'verifyingContract', type: 'address' }, | ||
], | ||
Person: [ | ||
{ name: 'name', type: 'string' }, | ||
{ name: 'wallet', type: 'address' }, | ||
], | ||
Mail: [ | ||
{ name: 'from', type: 'Person' }, | ||
{ name: 'to', type: 'Person' }, | ||
{ name: 'contents', type: 'string' }, | ||
], | ||
}, | ||
primaryType: 'Mail', | ||
domain: { | ||
name: 'Ether Mail', | ||
version: '1', | ||
chainId: 1, | ||
verifyingContract: '0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC', | ||
}, | ||
message: { | ||
from: { name: 'Cow', wallet: '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826' }, | ||
to: { name: 'Bob', wallet: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB' }, | ||
contents: 'Hello, Bob!', | ||
}, | ||
}; | ||
const privateKey = keccak_256('cow'); | ||
const address = addr.fromPrivateKey(privateKey); | ||
// address === '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826'; | ||
// typed.encodeData(typedData) === '0xa0ce...' | ||
); | ||
const e = typed.encoder(typedData.types, typedData.domain); | ||
// e._getHash(typedData.primaryType, typedData.message) == '0xbe60...'; | ||
const sig = | ||
'0x4355c47d63924e8a72e509b65029052eb6c299d53a04e167c5775fd466751c9d' + | ||
'07299936d304c153f6443dfa05f40ff007d72911b6f72307f996231605b91562' + | ||
(28).toString(16); | ||
// e.sign(typedData.primaryType, typedData.message, privateKey) === sig; | ||
// e.verify(typedData.primaryType, sig, typedData.message, address) === true; | ||
// e.recoverPublicKey(typedData.primaryType, sig, typedData.message) === address; | ||
// // Utils | ||
// typed.signTyped(typedData, privateKey) === sig; | ||
// typed.verifyTyped(sig, typedData, address) === true; | ||
// typed.recoverPublicKeyTyped(sig, typedData) === address; | ||
``` | ||
@@ -381,2 +435,30 @@ | ||
#### KZG EIP-4844 proofs | ||
```ts | ||
import { KZG } from 'micro-eth-signer/kzg'; | ||
import { trustedSetup } from 'trusted-setups'; // 400kb, 4-sec init | ||
import { trustedSetup as fastSetup } from 'trusted-setups/fast.js'; // 800kb, instant init | ||
const kzg = new KZG(trustedSetup); | ||
// kzg.computeProof(blob, z); | ||
// kzg.verifyBlobProof(blobs, commitments, proofs); | ||
``` | ||
All methods: | ||
```ts | ||
type Blob = string | string[] | bigint[]; | ||
type Scalar = string | bigint; | ||
export declare class KZG { | ||
constructor(setup: SetupData); | ||
computeProof(blob: Blob, z: bigint | string): [string, string]; | ||
verifyProof(commitment: string, z: Scalar, y: Scalar, proof: string): boolean; | ||
blobToKzgCommitment(blob: Blob): string; | ||
computeBlobProof(blob: Blob, commitment: string): string; | ||
verifyBlobProof(blob: Blob, commitment: string, proof: string): boolean; | ||
verifyBlobProofBatch(blobs: string[], commitments: string[], proofs: string[]): boolean; | ||
} | ||
``` | ||
#### Send whole account balance | ||
@@ -383,0 +465,0 @@ |
import * as P from 'micro-packed'; | ||
import * as abi from './abi/decoder.js'; | ||
import * as typed from './typed-data.js'; | ||
// Should not be included in npm package, just for test of typescript compilation | ||
@@ -194,1 +195,95 @@ const assertType = <T>(_value: T) => {}; | ||
}>(abi.events(TRANSFER_EVENT)); | ||
// Typed data | ||
const types = { | ||
Person: [ | ||
{ name: 'name', type: 'string' }, | ||
{ name: 'wallet', type: 'address' }, | ||
] as const, | ||
Mail: [ | ||
{ name: 'from', type: 'Person' }, | ||
{ name: 'to', type: 'Person' }, | ||
{ name: 'contents', type: 'string' }, | ||
] as const, | ||
Group: [ | ||
{ name: 'members', type: 'Person[]' }, | ||
{ name: 'owner', type: 'Person' }, | ||
] as const, | ||
Complex0: [ | ||
{ name: 'data', type: 'string[][]' }, // Complex array type | ||
{ name: 'info', type: 'Mail' }, | ||
] as const, | ||
Complex1: [ | ||
{ name: 'data', type: 'string[][][]' }, // Complex array type | ||
{ name: 'info', type: 'Mail' }, | ||
] as const, | ||
Complex: [ | ||
{ name: 'data', type: 'string[][3][]' }, // Complex array type | ||
{ name: 'info', type: 'Mail' }, | ||
] as const, | ||
} as const; | ||
assertType<{ | ||
from?: { name: string; wallet: string }; | ||
to?: { name: string; wallet: string }; | ||
contents: string; | ||
}>(1 as any as typed.GetType<typeof types, 'Mail'>); | ||
assertType<{ | ||
name: string; | ||
wallet: string; | ||
}>(1 as any as typed.GetType<typeof types, 'Person'>); | ||
assertType<{ | ||
members: ({ name: string; wallet: string } | undefined)[]; | ||
owner?: { name: string; wallet: string }; | ||
}>(1 as any as typed.GetType<typeof types, 'Group'>); | ||
assertType<{ | ||
data: string[][]; | ||
info?: { | ||
from?: { name: string; wallet: string }; | ||
to?: { name: string; wallet: string }; | ||
contents: string; | ||
}; | ||
}>(1 as any as typed.GetType<typeof types, 'Complex0'>); | ||
assertType<{ | ||
data: string[][][]; | ||
info?: { | ||
from?: { name: string; wallet: string }; | ||
to?: { name: string; wallet: string }; | ||
contents: string; | ||
}; | ||
}>(1 as any as typed.GetType<typeof types, 'Complex1'>); | ||
assertType<{ | ||
data: string[][][]; | ||
info?: { | ||
from?: { name: string; wallet: string }; | ||
to?: { name: string; wallet: string }; | ||
contents: string; | ||
}; | ||
}>(1 as any as typed.GetType<typeof types, 'Complex'>); | ||
const recursiveTypes = { | ||
Node: [ | ||
{ name: 'value', type: 'string' }, | ||
{ name: 'children', type: 'Node[]' }, | ||
] as const, | ||
} as const; | ||
type NodeType = typed.GetType<typeof recursiveTypes, 'Node'>; | ||
assertType<{ | ||
value: string; | ||
children: (NodeType | undefined)[]; | ||
}>(1 as any as typed.GetType<typeof recursiveTypes, 'Node'>); | ||
// const e = typed.encoder(types); | ||
// e.encodeData('Person', { name: 'test', wallet: 'x' }); | ||
// e.sign({ primaryType: 'Person', message: { name: 'test', wallet: 'x' }, domain: {} }, ''); | ||
// e.encodeData('Person', { name: 'test', wallet: 1n }); // should fail | ||
// e.sign({ primaryType: 'Person', message: {name: 'test'}, domain: {} }, ''); // should fail | ||
// e.sign({ primaryType: 'Person', message: {name: 'test', wallet: '', s: 3}, domain: {} }, ''); // should fail |
import { keccak_256 } from '@noble/hashes/sha3'; | ||
import { bytesToHex, concatBytes, hexToBytes } from '@noble/hashes/utils'; | ||
import * as P from 'micro-packed'; | ||
import { Web3CallArgs, Web3Provider, add0x, strip0x, omit, zip } from '../utils.js'; | ||
import { Web3CallArgs, IWeb3Provider, add0x, strip0x, omit, zip } from '../utils.js'; | ||
@@ -100,17 +100,2 @@ /* | ||
type ByteType = `bytes${ByteIdxType}`; | ||
// Arrays | ||
// We support fixed size arrays up to bytes[999], 2d up to bytees[39][39] | ||
// 1-9 | ||
type DigitsType = '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'; | ||
// 1-39 | ||
type ThrityDigits = DigitsType | `${'1' | '2' | '3'}${'0' | DigitsType}`; | ||
// 1-99 | ||
type TwoDigits = DigitsType | `${DigitsType}${'0' | DigitsType}`; | ||
// 1-999 | ||
type ThreeDigits = TwoDigits | `${TwoDigits}${'0' | DigitsType}`; | ||
// For static 1d arrays: 1-999: string[], string[1], ..., string[999] | ||
type ArrType<T extends string> = `${T}[${'' | ThreeDigits}]`; | ||
// For 2d arrays 1-39 per dimension (99 is too slow, 9k types): | ||
// string[][], string[][1], ..., string[39][39] | ||
type Arr2dType<T extends string> = `${T}[${'' | ThrityDigits}][${'' | ThrityDigits}]`; | ||
@@ -131,21 +116,17 @@ // [{name: 'a', type: 'string'}, {name: 'b', type: 'uint'}] -> {a: string, b: bigint}; | ||
// prettier-ignore | ||
export type GetType<T extends string> = | ||
T extends `${infer Base}[]${infer Rest}` ? GetType<`${Base}${Rest}`>[] : // 'string[]' -> 'string'[] | ||
T extends `${infer Base}[${number}]${infer Rest}` ? GetType<`${Base}${Rest}`>[] : // 'string[3]' -> 'string'[] | ||
T extends 'address' ? string : | ||
T extends 'string' ? string : | ||
T extends 'bool' ? boolean : | ||
T extends NumberType ? bigint : | ||
T extends ByteType ? Uint8Array : | ||
unknown; // default | ||
// prettier-ignore | ||
export type MapType<T extends BaseComponent> = | ||
T extends Component<'string'> ? string : | ||
T extends Component<ArrType<'string'>> ? string[] : | ||
T extends Component<Arr2dType<'string'>> ? string[][] : | ||
T extends Component<'address'> ? string : | ||
T extends Component<ArrType<'address'>> ? string[] : | ||
T extends Component<Arr2dType<'address'>> ? string[][] : | ||
T extends Component<'bool'> ? boolean : | ||
T extends Component<ArrType<'bool'>> ? boolean[] : | ||
T extends Component<Arr2dType<'bool'>> ? boolean[][] : | ||
T extends Component<NumberType> ? bigint : | ||
T extends Component<ArrType<NumberType>> ? bigint[] : | ||
T extends Component<Arr2dType<NumberType>> ? bigint[][] : | ||
T extends Component<ByteType> ? Uint8Array : | ||
T extends Component<ArrType<ByteType>> ? Uint8Array[] : | ||
T extends Component<Arr2dType<ByteType>> ? Uint8Array[][] : | ||
T extends Tuple<Array<Component<string>>> ? MapTuple<T['components']> : | ||
// Default | ||
unknown; | ||
T extends Component<infer Type> ? GetType<Type> : | ||
unknown; // default | ||
@@ -324,3 +305,3 @@ // Re-use ptr for len. u32 should be enough. | ||
? { | ||
[K in F[number] as K['name']]: N extends Web3Provider | ||
[K in F[number] as K['name']]: N extends IWeb3Provider | ||
? ContractMethodNet<K> | ||
@@ -359,5 +340,5 @@ : ContractMethod<K>; | ||
abi: T, | ||
net: Web3Provider, | ||
net: IWeb3Provider, | ||
contract?: string | ||
): ContractType<Writable<T>, Web3Provider>; | ||
): ContractType<Writable<T>, IWeb3Provider>; | ||
export function createContract<T extends ArrLike<FnArg>>( | ||
@@ -370,3 +351,3 @@ abi: T, | ||
abi: T, | ||
net?: Web3Provider, | ||
net?: IWeb3Provider, | ||
contract?: string | ||
@@ -373,0 +354,0 @@ ): ContractType<Writable<T>, undefined> { |
@@ -1,2 +0,2 @@ | ||
import { Web3Provider, Web3CallArgs, hexToNumber, amounts } from '../utils.js'; | ||
import { IWeb3Provider, Web3CallArgs, hexToNumber, amounts } from '../utils.js'; | ||
import { Transaction } from '../index.js'; | ||
@@ -342,3 +342,3 @@ import { TxVersions, legacySig } from '../tx.js'; | ||
*/ | ||
export class ArchiveNodeProvider implements Web3Provider { | ||
export class Web3Provider implements IWeb3Provider { | ||
constructor(private rpc: JsonrpcInterface) {} | ||
@@ -345,0 +345,0 @@ |
import { createContract, tokenFromSymbol } from '../abi/index.js'; | ||
import { Web3Provider, createDecimal } from '../utils.js'; | ||
import { IWeb3Provider, createDecimal } from '../utils.js'; | ||
@@ -284,3 +284,3 @@ const ABI = [ | ||
export default class Chainlink { | ||
constructor(readonly net: Web3Provider) {} | ||
constructor(readonly net: IWeb3Provider) {} | ||
async price(contract: string, decimals: number): Promise<number> { | ||
@@ -287,0 +287,0 @@ const prices = createContract(ABI, this.net, contract); |
import { keccak_256 } from '@noble/hashes/sha3'; | ||
import { concatBytes } from '@noble/hashes/utils'; | ||
import { createContract } from '../abi/decoder.js'; | ||
import { Web3Provider, strip0x } from '../utils.js'; | ||
import { IWeb3Provider, strip0x } from '../utils.js'; | ||
@@ -41,3 +41,3 @@ // No support for IDN names | ||
constructor(readonly net: Web3Provider) {} | ||
constructor(readonly net: IWeb3Provider) {} | ||
@@ -44,0 +44,0 @@ async getResolver(name: string): Promise<string | undefined> { |
import Chainlink from './chainlink.js'; | ||
import ENS from './ens.js'; | ||
import { ArchiveNodeProvider, calcTransfersDiff } from './archive.js'; | ||
import { Web3Provider, calcTransfersDiff } from './archive.js'; | ||
import UniswapV2 from './uniswap-v2.js'; | ||
@@ -8,2 +8,2 @@ import UniswapV3 from './uniswap-v3.js'; | ||
// There are many low level APIs inside which are not exported yet. | ||
export { ArchiveNodeProvider, calcTransfersDiff, Chainlink, ENS, UniswapV2, UniswapV3 }; | ||
export { Web3Provider, calcTransfersDiff, Chainlink, ENS, UniswapV2, UniswapV3 }; |
@@ -1,2 +0,2 @@ | ||
import { Web3Provider, ethHex, weieth, isBytes, createDecimal } from '../utils.js'; | ||
import { IWeb3Provider, ethHex, weieth, isBytes, createDecimal } from '../utils.js'; | ||
import { addr } from '../index.js'; | ||
@@ -127,3 +127,3 @@ import { tokenFromSymbol } from '../abi/index.js'; | ||
): any; | ||
constructor(public net: Web3Provider) {} | ||
constructor(public net: IWeb3Provider) {} | ||
// private async coinInfo(netName: string) { | ||
@@ -130,0 +130,0 @@ // if (!validateAddr(netName)) return; |
import { keccak_256 } from '@noble/hashes/sha3'; | ||
import { concatBytes, hexToBytes } from '@noble/hashes/utils'; | ||
import { Web3Provider, ethHex } from '../utils.js'; | ||
import { IWeb3Provider, ethHex } from '../utils.js'; | ||
import { ContractInfo, createContract } from '../abi/decoder.js'; | ||
@@ -35,3 +35,3 @@ import { default as UNISWAP_V2_ROUTER, UNISWAP_V2_ROUTER_CONTRACT } from '../abi/uniswap-v2.js'; | ||
async function reserves(net: Web3Provider, a: string, b: string): Promise<[bigint, bigint]> { | ||
async function reserves(net: IWeb3Provider, a: string, b: string): Promise<[bigint, bigint]> { | ||
a = uni.wrapContract(a); | ||
@@ -70,3 +70,3 @@ b = uni.wrapContract(b); | ||
async function bestPath( | ||
net: Web3Provider, | ||
net: IWeb3Provider, | ||
tokenA: string, | ||
@@ -73,0 +73,0 @@ tokenB: string, |
import { concatBytes } from '@noble/hashes/utils'; | ||
import { ContractInfo, createContract } from '../abi/decoder.js'; | ||
import { Web3Provider, ethHex } from '../utils.js'; | ||
import { IWeb3Provider, ethHex } from '../utils.js'; | ||
import { default as UNISWAP_V3_ROUTER, UNISWAP_V3_ROUTER_CONTRACT } from '../abi/uniswap-v3.js'; | ||
@@ -84,3 +84,3 @@ import * as uni from './uniswap-common.js'; | ||
async function bestPath( | ||
net: Web3Provider, | ||
net: IWeb3Provider, | ||
a: string, | ||
@@ -87,0 +87,0 @@ b: string, |
@@ -19,3 +19,3 @@ import { isBytes as _isBytes, hexToBytes as _hexToBytes, bytesToHex } from '@noble/hashes/utils'; | ||
export type Web3Provider = { | ||
export type IWeb3Provider = { | ||
ethCall: (args: Web3CallArgs) => Promise<string>; | ||
@@ -95,3 +95,3 @@ estimateGas: (args: Web3CallArgs) => Promise<bigint>; | ||
export function isObject(item: unknown): item is object { | ||
export function isObject(item: unknown): item is Record<string, any> { | ||
return item != null && typeof item === 'object'; | ||
@@ -98,0 +98,0 @@ } |
@@ -14,3 +14,3 @@ import { isBytes as _isBytes } from '@noble/hashes/utils'; | ||
}>; | ||
export type Web3Provider = { | ||
export type IWeb3Provider = { | ||
ethCall: (args: Web3CallArgs) => Promise<string>; | ||
@@ -41,3 +41,3 @@ estimateGas: (args: Web3CallArgs) => Promise<bigint>; | ||
export declare function hexToNumber(hex: string): bigint; | ||
export declare function isObject(item: unknown): item is object; | ||
export declare function isObject(item: unknown): item is Record<string, any>; | ||
export declare function astr(str: unknown): void; | ||
@@ -44,0 +44,0 @@ export declare function cloneDeep<T>(obj: T): T; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
1548592
230
24602
535
+ Added@noble/curves@1.6.0(transitive)
+ Added@noble/hashes@1.5.0(transitive)
- Removed@noble/curves@1.4.2(transitive)
- Removed@noble/hashes@1.4.0(transitive)
Updated@noble/curves@~1.6.0
Updated@noble/hashes@~1.5.0