Socket
Socket
Sign inDemoInstall

micro-eth-signer

Package Overview
Dependencies
4
Maintainers
0
Versions
37
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.9.1 to 0.10.0

esm/_type_test.d.ts

7

abi/common.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.addHook = exports.addHints = exports.addHint = void 0;
exports.addHint = addHint;
exports.addHints = addHints;
exports.addHook = addHook;
function addHint(abi, name, fn) {

@@ -14,3 +16,2 @@ const res = [];

}
exports.addHint = addHint;
function addHints(abi, map) {

@@ -27,3 +28,2 @@ const res = [];

}
exports.addHints = addHints;
function addHook(abi, name, fn) {

@@ -39,3 +39,2 @@ const res = [];

}
exports.addHook = addHook;
//# sourceMappingURL=common.js.map
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Decoder = exports.events = exports.createContract = exports.fnSigHash = exports.evSigHash = exports.mapArgs = exports.mapComponent = void 0;
exports.Decoder = void 0;
exports.mapComponent = mapComponent;
exports.mapArgs = mapArgs;
exports.evSigHash = evSigHash;
exports.fnSigHash = fnSigHash;
exports.createContract = createContract;
exports.events = events;
const sha3_1 = require("@noble/hashes/sha3");

@@ -135,3 +141,2 @@ const utils_1 = require("@noble/hashes/utils");

}
exports.mapComponent = mapComponent;
// Because args and output are not tuple

@@ -160,3 +165,2 @@ // TODO: try merge with mapComponent

}
exports.mapArgs = mapArgs;
function fnSignature(o) {

@@ -178,7 +182,5 @@ if (!o.type)

}
exports.evSigHash = evSigHash;
function fnSigHash(o) {
return evSigHash(o).slice(0, 8);
}
exports.fnSigHash = fnSigHash;
function createContract(abi, net, contract) {

@@ -229,3 +231,2 @@ // Find non-uniq function names so we can handle overloads

}
exports.createContract = createContract;
// TODO: try to simplify further

@@ -315,3 +316,2 @@ function events(abi) {

}
exports.events = events;
class Decoder {

@@ -318,0 +318,0 @@ constructor() {

@@ -111,3 +111,3 @@ /*! micro-eth-signer - MIT License (c) 2021 Paul Miller (paulmillr.com) */

throw new Error('account balance must be bigger than 0');
const { fee } = this.calcAmounts().wei;
const fee = this.fee;
const amountToSend = accountBalance - fee;

@@ -178,3 +178,4 @@ if (amountToSend <= 0n)

}
calcAmounts() {
// Calculates MAXIMUM fee in wei that could be spent
get fee() {
const { type, raw } = this;

@@ -195,12 +196,3 @@ // Fee calculation is not exact, real fee can be smaller

// TODO: how to calculate 4844 fee?
const fee = raw.gasLimit * gasFee;
const amount = raw.value;
const amountWithFee = fee + amount;
const wei = { amount, fee, amountWithFee };
const humanized = {
amount: weieth.encode(amount),
fee: weieth.encode(fee),
amountWithFee: weieth.encode(amountWithFee),
};
return { wei, humanized };
return raw.gasLimit * gasFee;
}

@@ -207,0 +199,0 @@ clone() {

@@ -1,2 +0,2 @@

import { amounts } from '../utils.js';
import { hexToNumber, amounts } from '../utils.js';
import { Transaction } from '../index.js';

@@ -169,12 +169,17 @@ import { TxVersions, legacySig } from '../tx.js';

export class ArchiveNodeProvider {
constructor(provider) {
this.provider = provider;
constructor(rpc) {
this.rpc = rpc;
}
// The low-level place where network calls are done
rpc(method, ...args) {
return this.provider.call(method, ...args);
call(method, ...args) {
return this.rpc.call(method, ...args);
}
ethCall(args, tag = 'latest') {
return this.rpc.call('eth_call', args, tag);
}
async estimateGas(args, tag = 'latest') {
return hexToNumber(await this.rpc.call('eth_estimateGas', args, tag));
}
// Timestamp is available only inside blocks
async blockInfo(block) {
const res = await this.rpc('eth_getBlockByNumber', ethNum(block), false);
const res = await this.call('eth_getBlockByNumber', ethNum(block), false);
fixBlock(res);

@@ -185,4 +190,4 @@ return res;

let [balance, nonce] = await Promise.all([
this.rpc('eth_getBalance', address, 'latest'),
this.rpc('eth_getTransactionCount', address, 'latest'),
this.call('eth_getBalance', address, 'latest'),
this.call('eth_getTransactionCount', address, 'latest'),
]);

@@ -201,6 +206,6 @@ balance = BigInt(balance);

async height() {
return Number.parseInt(await this.rpc('eth_blockNumber'));
return Number.parseInt(await this.call('eth_blockNumber'));
}
async traceFilterSingle(address, opts = {}) {
const res = await this.rpc('trace_filter', {
const res = await this.call('trace_filter', {
fromBlock: ethNum(opts.fromBlock),

@@ -243,3 +248,3 @@ toBlock: ethNum(opts.toBlock),

params.count = opts.perRequest;
const res = await this.rpc('trace_filter', params);
const res = await this.call('trace_filter', params);
if (!res.length)

@@ -262,3 +267,3 @@ break;

req.toBlock = ethNum(opts.toBlock);
const res = await this.rpc('eth_getLogs', req);
const res = await this.call('eth_getLogs', req);
return res.map((i) => fixLog(i, opts));

@@ -302,4 +307,4 @@ }

let [info, receipt] = await Promise.all([
this.rpc('eth_getTransactionByHash', txHash),
this.rpc('eth_getTransactionReceipt', txHash),
this.call('eth_getTransactionByHash', txHash),
this.call('eth_getTransactionReceipt', txHash),
]);

@@ -358,3 +363,3 @@ info = fixTxInfo(info);

try {
let c = createContract(ERC20, this.provider, address);
let c = createContract(ERC20, this, address);
const [symbol, decimals] = await Promise.all([c.symbol.call(), c.decimals.call()]);

@@ -499,3 +504,3 @@ return { contract: address, abi: 'ERC20', symbol, decimals: Number(decimals) };

async tokenBalances(address, tokens) {
const balances = await Promise.all(tokens.map((i) => createContract(ERC20, this.provider, i).balanceOf.call(address)));
const balances = await Promise.all(tokens.map((i) => createContract(ERC20, this, i).balanceOf.call(address)));
return Object.fromEntries(tokens.map((i, j) => [i, balances[j]]));

@@ -502,0 +507,0 @@ }

import Chainlink from './chainlink.js';
import ENS from './ens.js';
import FetchProvider from './provider.js';
import { ArchiveNodeProvider, calcTransfersDiff } from './archive.js';

@@ -8,3 +7,3 @@ import UniswapV2 from './uniswap-v2.js';

// There are many low level APIs inside which are not exported yet.
export { ArchiveNodeProvider, calcTransfersDiff, Chainlink, ENS, FetchProvider, UniswapV2, UniswapV3, };
export { ArchiveNodeProvider, calcTransfersDiff, Chainlink, ENS, UniswapV2, UniswapV3 };
//# sourceMappingURL=index.js.map

@@ -93,14 +93,3 @@ import { addr } from './address.js';

private calcHash;
calcAmounts(): {
wei: {
amount: bigint;
fee: bigint;
amountWithFee: bigint;
};
humanized: {
amount: string;
fee: string;
amountWithFee: string;
};
};
get fee(): bigint;
clone(): Transaction<T>;

@@ -107,0 +96,0 @@ verifySignature(): boolean;

@@ -116,3 +116,3 @@ "use strict";

throw new Error('account balance must be bigger than 0');
const { fee } = this.calcAmounts().wei;
const fee = this.fee;
const amountToSend = accountBalance - fee;

@@ -183,3 +183,4 @@ if (amountToSend <= 0n)

}
calcAmounts() {
// Calculates MAXIMUM fee in wei that could be spent
get fee() {
const { type, raw } = this;

@@ -200,12 +201,3 @@ // Fee calculation is not exact, real fee can be smaller

// TODO: how to calculate 4844 fee?
const fee = raw.gasLimit * gasFee;
const amount = raw.value;
const amountWithFee = fee + amount;
const wei = { amount, fee, amountWithFee };
const humanized = {
amount: utils_js_1.weieth.encode(amount),
fee: utils_js_1.weieth.encode(fee),
amountWithFee: utils_js_1.weieth.encode(amountWithFee),
};
return { wei, humanized };
return raw.gasLimit * gasFee;
}

@@ -212,0 +204,0 @@ clone() {

@@ -1,2 +0,2 @@

import { Web3Provider } from '../utils.js';
import { Web3Provider, Web3CallArgs } from '../utils.js';
import { TxVersions } from '../tx.js';

@@ -104,3 +104,3 @@ import { ContractInfo } from '../abi/index.js';

balance: bigint;
value?: number;
nonce: number;
active: boolean;

@@ -170,2 +170,5 @@ };

export type TxAllowances = Record<string, Record<string, bigint>>;
export type JsonrpcInterface = {
call: (method: string, ...args: any[]) => Promise<any>;
};
/**

@@ -178,14 +181,10 @@ * Transaction-related code around Web3Provider.

*/
export declare class ArchiveNodeProvider {
private provider;
constructor(provider: Web3Provider);
export declare class ArchiveNodeProvider implements Web3Provider {
private rpc;
constructor(rpc: JsonrpcInterface);
call(method: string, ...args: any[]): Promise<any>;
ethCall(args: Web3CallArgs, tag?: string): Promise<any>;
estimateGas(args: Web3CallArgs, tag?: string): Promise<bigint>;
blockInfo(block: number): Promise<BlockInfo>;
unspent(address: string): Promise<{
symbol: string;
decimals: number;
balance: any;
nonce: any;
active: boolean;
}>;
unspent(address: string): Promise<Unspent>;
height(): Promise<number>;

@@ -192,0 +191,0 @@ traceFilterSingle(address: string, opts?: TraceOpts): Promise<any>;

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.calcTransfersDiff = exports.ArchiveNodeProvider = void 0;
exports.ArchiveNodeProvider = void 0;
exports.calcTransfersDiff = calcTransfersDiff;
const utils_js_1 = require("../utils.js");

@@ -172,12 +173,17 @@ const index_js_1 = require("../index.js");

class ArchiveNodeProvider {
constructor(provider) {
this.provider = provider;
constructor(rpc) {
this.rpc = rpc;
}
// The low-level place where network calls are done
rpc(method, ...args) {
return this.provider.call(method, ...args);
call(method, ...args) {
return this.rpc.call(method, ...args);
}
ethCall(args, tag = 'latest') {
return this.rpc.call('eth_call', args, tag);
}
async estimateGas(args, tag = 'latest') {
return (0, utils_js_1.hexToNumber)(await this.rpc.call('eth_estimateGas', args, tag));
}
// Timestamp is available only inside blocks
async blockInfo(block) {
const res = await this.rpc('eth_getBlockByNumber', ethNum(block), false);
const res = await this.call('eth_getBlockByNumber', ethNum(block), false);
fixBlock(res);

@@ -188,4 +194,4 @@ return res;

let [balance, nonce] = await Promise.all([
this.rpc('eth_getBalance', address, 'latest'),
this.rpc('eth_getTransactionCount', address, 'latest'),
this.call('eth_getBalance', address, 'latest'),
this.call('eth_getTransactionCount', address, 'latest'),
]);

@@ -204,6 +210,6 @@ balance = BigInt(balance);

async height() {
return Number.parseInt(await this.rpc('eth_blockNumber'));
return Number.parseInt(await this.call('eth_blockNumber'));
}
async traceFilterSingle(address, opts = {}) {
const res = await this.rpc('trace_filter', {
const res = await this.call('trace_filter', {
fromBlock: ethNum(opts.fromBlock),

@@ -246,3 +252,3 @@ toBlock: ethNum(opts.toBlock),

params.count = opts.perRequest;
const res = await this.rpc('trace_filter', params);
const res = await this.call('trace_filter', params);
if (!res.length)

@@ -265,3 +271,3 @@ break;

req.toBlock = ethNum(opts.toBlock);
const res = await this.rpc('eth_getLogs', req);
const res = await this.call('eth_getLogs', req);
return res.map((i) => fixLog(i, opts));

@@ -305,4 +311,4 @@ }

let [info, receipt] = await Promise.all([
this.rpc('eth_getTransactionByHash', txHash),
this.rpc('eth_getTransactionReceipt', txHash),
this.call('eth_getTransactionByHash', txHash),
this.call('eth_getTransactionReceipt', txHash),
]);

@@ -361,3 +367,3 @@ info = fixTxInfo(info);

try {
let c = (0, index_js_2.createContract)(index_js_2.ERC20, this.provider, address);
let c = (0, index_js_2.createContract)(index_js_2.ERC20, this, address);
const [symbol, decimals] = await Promise.all([c.symbol.call(), c.decimals.call()]);

@@ -502,3 +508,3 @@ return { contract: address, abi: 'ERC20', symbol, decimals: Number(decimals) };

async tokenBalances(address, tokens) {
const balances = await Promise.all(tokens.map((i) => (0, index_js_2.createContract)(index_js_2.ERC20, this.provider, i).balanceOf.call(address)));
const balances = await Promise.all(tokens.map((i) => (0, index_js_2.createContract)(index_js_2.ERC20, this, i).balanceOf.call(address)));
return Object.fromEntries(tokens.map((i, j) => [i, balances[j]]));

@@ -548,3 +554,2 @@ }

}
exports.calcTransfersDiff = calcTransfersDiff;
//# sourceMappingURL=archive.js.map
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.namehash = void 0;
exports.namehash = namehash;
const sha3_1 = require("@noble/hashes/sha3");

@@ -17,3 +17,2 @@ const utils_1 = require("@noble/hashes/utils");

}
exports.namehash = namehash;
class ENS {

@@ -20,0 +19,0 @@ constructor(net) {

import Chainlink from './chainlink.js';
import ENS from './ens.js';
import FetchProvider from './provider.js';
import { ArchiveNodeProvider, calcTransfersDiff } from './archive.js';
import UniswapV2 from './uniswap-v2.js';
import UniswapV3 from './uniswap-v3.js';
export { ArchiveNodeProvider, calcTransfersDiff, Chainlink, ENS, FetchProvider, UniswapV2, UniswapV3, };
export { ArchiveNodeProvider, calcTransfersDiff, Chainlink, ENS, UniswapV2, UniswapV3 };
//# sourceMappingURL=index.d.ts.map
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.UniswapV3 = exports.UniswapV2 = exports.FetchProvider = exports.ENS = exports.Chainlink = exports.calcTransfersDiff = exports.ArchiveNodeProvider = void 0;
exports.UniswapV3 = exports.UniswapV2 = exports.ENS = exports.Chainlink = exports.calcTransfersDiff = exports.ArchiveNodeProvider = void 0;
const chainlink_js_1 = require("./chainlink.js");

@@ -8,4 +8,2 @@ exports.Chainlink = chainlink_js_1.default;

exports.ENS = ens_js_1.default;
const provider_js_1 = require("./provider.js");
exports.FetchProvider = provider_js_1.default;
const archive_js_1 = require("./archive.js");

@@ -12,0 +10,0 @@ Object.defineProperty(exports, "ArchiveNodeProvider", { enumerable: true, get: function () { return archive_js_1.ArchiveNodeProvider; } });

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.UniswapAbstract = exports.isValidUniAddr = exports.isValidEthAddr = exports.sortTokens = exports.wrapContract = exports.WETH = exports.COMMON_BASES = exports.awaitDeep = exports.isPromise = exports.addPercent = exports.DEFAULT_SWAP_OPT = void 0;
exports.UniswapAbstract = exports.WETH = exports.COMMON_BASES = exports.DEFAULT_SWAP_OPT = void 0;
exports.addPercent = addPercent;
exports.isPromise = isPromise;
exports.awaitDeep = awaitDeep;
exports.wrapContract = wrapContract;
exports.sortTokens = sortTokens;
exports.isValidEthAddr = isValidEthAddr;
exports.isValidUniAddr = isValidUniAddr;
const utils_js_1 = require("../utils.js");

@@ -13,3 +20,2 @@ const index_js_1 = require("../index.js");

}
exports.addPercent = addPercent;
function isPromise(o) {

@@ -20,3 +26,2 @@ if (!o || !['object', 'function'].includes(typeof o))

}
exports.isPromise = isPromise;
async function awaitDeep(o, ignore_errors) {

@@ -63,3 +68,2 @@ let promises = [];

}
exports.awaitDeep = awaitDeep;
exports.COMMON_BASES = ['WETH', 'DAI', 'USDC', 'USDT', 'COMP', 'MKR', 'WBTC', 'AMPL']

@@ -75,3 +79,2 @@ .map((i) => (0, index_js_2.tokenFromSymbol)(i))

}
exports.wrapContract = wrapContract;
function sortTokens(a, b) {

@@ -84,11 +87,8 @@ a = wrapContract(a);

}
exports.sortTokens = sortTokens;
function isValidEthAddr(address) {
return index_js_1.addr.isValid(address);
}
exports.isValidEthAddr = isValidEthAddr;
function isValidUniAddr(address) {
return address === 'eth' || isValidEthAddr(address);
}
exports.isValidUniAddr = isValidUniAddr;
function getToken(token) {

@@ -95,0 +95,0 @@ if (typeof token === 'string' && token.toLowerCase() === 'eth')

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.txData = exports.amount = exports.pairAddress = exports.create2 = void 0;
exports.create2 = create2;
exports.pairAddress = pairAddress;
exports.amount = amount;
exports.txData = txData;
const sha3_1 = require("@noble/hashes/sha3");

@@ -27,3 +30,2 @@ const utils_1 = require("@noble/hashes/utils");

}
exports.create2 = create2;
function pairAddress(a, b, factory = FACTORY_ADDRESS) {

@@ -34,3 +36,2 @@ // This is completely broken: '0x11' '0x11' will return '0x1111'. But this is how it works in sdk.

}
exports.pairAddress = pairAddress;
async function reserves(net, a, b) {

@@ -63,3 +64,2 @@ a = uni.wrapContract(a);

}
exports.amount = amount;
async function bestPath(net, tokenA, tokenB, amountIn, amountOut) {

@@ -154,3 +154,2 @@ if ((amountIn && amountOut) || (!amountIn && !amountOut))

}
exports.txData = txData;
// Here goes Exchange API. Everything above is SDK. Supports almost everything from official sdk except liquidity stuff.

@@ -157,0 +156,0 @@ class UniswapV2 extends uni.UniswapAbstract {

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.txData = exports.Fee = void 0;
exports.Fee = void 0;
exports.txData = txData;
const utils_1 = require("@noble/hashes/utils");

@@ -162,3 +163,2 @@ const decoder_js_1 = require("../abi/decoder.js");

}
exports.txData = txData;
// Here goes Exchange API. Everything above is SDK.

@@ -165,0 +165,0 @@ class UniswapV3 extends uni.UniswapAbstract {

{
"name": "micro-eth-signer",
"version": "0.9.1",
"version": "0.10.0",
"description": "Minimal library for Ethereum transactions, addresses and smart contracts",
"files": ["abi", "esm", "net", "src", "*.js", "*.d.ts", "*.js.map", "*.d.ts.map"],
"files": [
"abi",
"esm",
"net",
"src",
"*.js",
"*.d.ts",
"*.js.map",
"*.d.ts.map"
],
"main": "index.js",
"module": "esm/index.js",
"types": "index.d.ts",
"types": "esm/index.d.ts",
"dependencies": {

@@ -17,6 +26,7 @@ "@noble/curves": "~1.4.0",

"micro-bmark": "0.3.1",
"micro-ftch": "0.4.0",
"micro-should": "0.4.0",
"prettier": "3.1.1",
"prettier": "3.3.2",
"snappyjs": "0.7.0",
"typescript": "5.3.2",
"typescript": "5.5.2",
"yaml": "2.4.1"

@@ -32,35 +42,28 @@ },

".": {
"types": "./index.d.ts",
"import": "./esm/index.js",
"default": "./index.js"
"require": "./index.js"
},
"./abi": {
"types": "./abi/index.d.ts",
"import": "./esm/abi/index.js",
"default": "./abi/index.js"
"require": "./abi/index.js"
},
"./net": {
"types": "./net/index.d.ts",
"import": "./esm/net/index.js",
"default": "./net/index.js"
"require": "./net/index.js"
},
"./rlp": {
"types": "./net/rlp.d.ts",
"import": "./esm/net/rlp.js",
"default": "./net/rlp.js"
"import": "./esm/rlp.js",
"require": "./rlp.js"
},
"./ssz": {
"types": "./net/ssz.d.ts",
"import": "./esm/net/ssz.js",
"default": "./net/ssz.js"
"import": "./esm/ssz.js",
"require": "./ssz.js"
},
"./tx": {
"types": "./tx.d.ts",
"import": "./esm/tx.js",
"default": "./tx.js"
"require": "./tx.js"
},
"./utils": {
"types": "./utils.d.ts",
"import": "./esm/utils.js",
"default": "./utils.js"
"require": "./utils.js"
}

@@ -67,0 +70,0 @@ },

@@ -6,3 +6,3 @@ # micro-eth-signer

- 🔓 Secure: 3 deps, audited [noble](https://paulmillr.com/noble/) cryptography, no network code
- 🔻 Tree-shaking-friendly: use only what's necessary, other code won't be included
- 🔻 Tree-shakeable: unused code is excluded from your builds
- 🔍 Reliable: 150MB of test vectors from EIPs, ethers and viem

@@ -28,6 +28,7 @@ - ✍️ Create, sign and decode transactions using human-readable hints

- [Create random wallet](#create-random-wallet)
- [Transactions: create, sign](#create-and-sign-transactions)
- [Addresses: create, checksum](#create-and-checksum-addresses)
- [Create random wallet](#create-random-wallet)
- [Network and smart contracts](#network-and-smart-contracts)
- [Init network](#init-network)
- [Fetch balances and history from an archive node](#fetch-balances-and-history-from-an-archive-node)

@@ -50,18 +51,26 @@ - [Fetch Chainlink oracle prices](#fetch-chainlink-oracle-prices)

### Create random wallet
```ts
import { addr } from 'micro-eth-signer';
const random = addr.random(); // Secure: uses CSPRNG
console.log(random.privateKey, random.address);
// '0x17ed046e6c4c21df770547fad9a157fd17b48b35fe9984f2ff1e3c6a62700bae'
// '0x26d930712fd2f612a107A70fd0Ad79b777cD87f6'
```
### Transactions: create, sign
```ts
import { addr, Transaction, weigwei, weieth } from 'micro-eth-signer';
const privKey = '0x6b911fd37cdf5c81d4c0adb1ab7fa822ed253ab0ad9aa18d77257c88b29b718e';
const senderAddr = addr.fromPrivateKey(privKey);
const unsignedTx = Transaction.prepare({
import { Transaction, weigwei, weieth } from 'micro-eth-signer';
const tx = Transaction.prepare({
to: '0xdf90dea0e0bf5ca6d2a7f0cb86874ba6714f463e',
maxFeePerGas: weigwei.decode('100'), // 100 gwei in wei
value: weieth.decode('1.1'), // 1.1 eth in wei
value: weieth.decode('1.1'), // 1.1eth in wei
maxFeePerGas: weigwei.decode('100'), // 100gwei in wei (priority fee is 1 gwei)
nonce: 0n,
});
const tx = unsignedTx.signBy(privKey); // Uint8Array is also accepted
console.log('signed tx', tx, tx.toHex());
console.log('need total', tx.calcAmounts()); // wei & humanized formats
console.log('address is same', tx.sender === senderAddr);
// Uses `random` from example above. Alternatively, pass 0x hex string or Uint8Array
const signedTx = tx.signBy(random.privateKey);
console.log('signed tx', signedTx, signedTx.toHex());
console.log('fee', signedTx.fee);
```

@@ -88,28 +97,41 @@

### Create random wallet
### Network and smart contracts
```ts
import { addr } from 'micro-eth-signer';
const random = addr.random(); // Secure: uses CSPRNG
console.log(random.privateKey, random.address);
// 0x17ed046e6c4c21df770547fad9a157fd17b48b35fe9984f2ff1e3c6a62700bae
// 0x26d930712fd2f612a107A70fd0Ad79b777cD87f6
```
A common problem in web3 libraries is how complex they are to audit with regards to network calls.
### Network and smart contracts
In eth-signer, all network calls are done with user-provided function, conforming to built-in `fetch()`:
We don't have _actual network code_ in the package:
all network code is deferred to FetchProvider, which must be initialized with a
method, conforming to built-in `fetch`. This means, you are able to completely control
all network requests.
1. This makes library network-free, which simplifies auditability
2. User fully controls all network requests
It's recommended to use [micro-ftch](https://github.com/paulmillr/micro-ftch),
which works on top of fetch and implements killswitch, logging, concurrency limits and other features.
#### Init network
Most APIs (chainlink, uniswap) expect instance of ArchiveNodeProvider.
The call stack would look like this:
- `Chainlink` => `ArchiveNodeProvider` => `jsonrpc` => `fetch`
To initialize ArchiveNodeProvider, do the following:
```js
// Requests are made with fetch(), a built-in method
import { jsonrpc } from 'micro-ftch';
import { ArchiveNodeProvider } from 'micro-eth-signer/net';
const RPC_URL = 'http://localhost:8545';
const prov = new ArchiveNodeProvider(jsonrpc(fetch, RPC_URL));
// Example using mewapi RPC
const RPC_URL_2 = 'https://nodes.mewapi.io/rpc/eth';
const prov2 = new ArchiveNodeProvider(
jsonrpc(fetch, RPC_URL_2, { Origin: 'https://www.myetherwallet.com' })
);
```
#### Fetch balances and history from an archive node
```ts
import { ArchiveNodeProvider, FetchProvider } from 'micro-eth-signer/net';
const RPC_URL = 'http://localhost:8545'; // URL to any RPC
const rpc = new FetchProvider(globalThis.fetch, RPC_URL); // use built-in fetch()
const prov = new ArchiveNodeProvider(rpc);
const addr = '0xd8da6bf26964af9d7eed9e03e53415d37aa96045';
const block = await prov.blockInfo(await prov.height());

@@ -119,5 +141,2 @@ console.log('current block', block.number, block.timestamp, block.baseFeePerGas);

// ENS example:
// import { ENS } from 'micro-eth-signer/net'; const ens = new ENS(rpc), addr = await ens.nameToAddress('vitalik.eth');
// Other methods of ArchiveNodeProvider:

@@ -147,7 +166,4 @@ // blockInfo(block: number): Promise<BlockInfo>; // {baseFeePerGas, hash, timestamp...}

```ts
import { FetchProvider, Chainlink } from 'micro-eth-signer/net';
const provider = new FetchProvider(thisGlobal.fetch, 'https://nodes.mewapi.io/rpc/eth', {
Origin: 'https://www.myetherwallet.com',
});
const link = new Chainlink(provider);
import { Chainlink } from 'micro-eth-signer/net';
const link = new Chainlink(prov);
const btc = await link.coinPrice('BTC');

@@ -161,6 +177,4 @@ const bat = await link.tokenPrice('BAT');

```ts
import { FetchProvider, ENS } from 'micro-eth-signer/net';
const RPC_URL = 'http://127.0.0.1:8545';
const provider = new FetchProvider(thisGlobal.fetch, RPC_URL);
const ens = new ENS(provider);
import { ENS } from 'micro-eth-signer/net';
const ens = new ENS(prov);
const vitalikAddr = await ens.nameToAddress('vitalik.eth');

@@ -179,11 +193,7 @@ ```

import { tokenFromSymbol } from 'micro-eth-signer/abi';
import { FetchProvider, UniswapV3 } from 'micro-eth-signer/net'; // or UniswapV2
import { UniswapV3 } from 'micro-eth-signer/net'; // or UniswapV2
const RPC_URL = 'https://nodes.mewapi.io/rpc/eth';
const provider = new FetchProvider(thisGlobal.fetch, RPC_URL, {
Origin: 'https://www.myetherwallet.com',
});
const USDT = tokenFromSymbol('USDT');
const BAT = tokenFromSymbol('BAT');
const u3 = new UniswapV3(provider); // or new UniswapV2(provider)
const u3 = new UniswapV3(prov); // or new UniswapV2(provider)
const fromAddress = '0xd8da6bf26964af9d7eed9e03e53415d37aa96045';

@@ -365,5 +375,5 @@ const toAddress = '0xd8da6bf26964af9d7eed9e03e53415d37aa96045';

import { addr, messenger } from 'micro-eth-signer';
const { privateKey, address } = addr.random();
const rand = addr.random();
const msg = 'noble';
const sig = messenger.sign(msg, privateKey);
const sig = messenger.sign(msg, rand.privateKey);
const isValid = messenger.verify(sig, msg, address);

@@ -370,0 +380,0 @@ ```

@@ -117,12 +117,13 @@ import { keccak_256 } from '@noble/hashes/sha3';

// [{name: 'a', type: 'string'}, {name: 'b', type: 'uint'}] -> {a: string, b: bigint};
export type MapTuple<T> = T extends ArrLike<Component<string> & { name: string }>
? {
[K in T[number] as K['name']]: MapType<K>;
}
: T extends ArrLike<Component<string>>
? // [{name: 'a', type: 'string'}, {type: 'uint'}] -> [string, bigint];
{
[K in keyof T]: T[K] extends BaseComponent ? MapType<T[K]> : unknown;
export type MapTuple<T> =
T extends ArrLike<Component<string> & { name: string }>
? {
[K in T[number] as K['name']]: MapType<K>;
}
: unknown;
: T extends ArrLike<Component<string>>
? // [{name: 'a', type: 'string'}, {type: 'uint'}] -> [string, bigint];
{
[K in keyof T]: T[K] extends BaseComponent ? MapType<T[K]> : unknown;
}
: unknown;

@@ -319,11 +320,10 @@ // prettier-ignore

export type ContractType<T extends Array<FnArg>, N, F = ContractTypeFilter<T>> = F extends ArrLike<
FunctionType & { name: string }
>
? {
[K in F[number] as K['name']]: N extends Web3Provider
? ContractMethodNet<K>
: ContractMethod<K>;
}
: never;
export type ContractType<T extends Array<FnArg>, N, F = ContractTypeFilter<T>> =
F extends ArrLike<FunctionType & { name: string }>
? {
[K in F[number] as K['name']]: N extends Web3Provider
? ContractMethodNet<K>
: ContractMethod<K>;
}
: never;

@@ -423,10 +423,8 @@ function fnSignature(o: FnArg): string {

export type ContractEventType<
T extends Array<FnArg>,
F = ContractEventTypeFilter<T>,
> = F extends ArrLike<EventType>
? {
[K in F[number] as K['name']]: EventMethod<K>;
}
: never;
export type ContractEventType<T extends Array<FnArg>, F = ContractEventTypeFilter<T>> =
F extends ArrLike<EventType>
? {
[K in F[number] as K['name']]: EventMethod<K>;
}
: never;

@@ -433,0 +431,0 @@ // TODO: try to simplify further

@@ -161,3 +161,3 @@ /*! micro-eth-signer - MIT License (c) 2021 Paul Miller (paulmillr.com) */

throw new Error('account balance must be bigger than 0');
const { fee } = this.calcAmounts().wei;
const fee = this.fee;
const amountToSend = accountBalance - fee;

@@ -225,3 +225,4 @@ if (amountToSend <= 0n) throw new Error('account balance must be bigger than fee of ' + fee);

}
calcAmounts() {
// Calculates MAXIMUM fee in wei that could be spent
get fee() {
const { type, raw } = this;

@@ -241,12 +242,3 @@ // Fee calculation is not exact, real fee can be smaller

// TODO: how to calculate 4844 fee?
const fee = raw.gasLimit * gasFee;
const amount = raw.value;
const amountWithFee = fee + amount;
const wei = { amount, fee, amountWithFee };
const humanized = {
amount: weieth.encode(amount),
fee: weieth.encode(fee),
amountWithFee: weieth.encode(amountWithFee),
};
return { wei, humanized };
return raw.gasLimit * gasFee;
}

@@ -253,0 +245,0 @@ clone() {

@@ -1,2 +0,2 @@

import { Web3Provider, amounts } from '../utils.js';
import { Web3Provider, Web3CallArgs, hexToNumber, amounts } from '../utils.js';
import { Transaction } from '../index.js';

@@ -151,3 +151,3 @@ import { TxVersions, legacySig } from '../tx.js';

balance: bigint;
value?: number;
nonce: number;
// useful for wallets to know if there was transactions related to wallet

@@ -332,2 +332,6 @@ // NOTE: even if nonce is zero, there can be transfers to wallet

export type JsonrpcInterface = {
call: (method: string, ...args: any[]) => Promise<any>;
};
/**

@@ -340,13 +344,18 @@ * Transaction-related code around Web3Provider.

*/
export class ArchiveNodeProvider {
constructor(private provider: Web3Provider) {}
export class ArchiveNodeProvider implements Web3Provider {
constructor(private rpc: JsonrpcInterface) {}
// The low-level place where network calls are done
private rpc(method: string, ...args: any[]) {
return this.provider.call(method, ...args);
call(method: string, ...args: any[]) {
return this.rpc.call(method, ...args);
}
ethCall(args: Web3CallArgs, tag = 'latest') {
return this.rpc.call('eth_call', args, tag);
}
async estimateGas(args: Web3CallArgs, tag = 'latest') {
return hexToNumber(await this.rpc.call('eth_estimateGas', args, tag));
}
// Timestamp is available only inside blocks
async blockInfo(block: number): Promise<BlockInfo> {
const res = await this.rpc('eth_getBlockByNumber', ethNum(block), false);
const res = await this.call('eth_getBlockByNumber', ethNum(block), false);
fixBlock(res);

@@ -356,6 +365,6 @@ return res;

async unspent(address: string) {
async unspent(address: string): Promise<Unspent> {
let [balance, nonce] = await Promise.all([
this.rpc('eth_getBalance', address, 'latest'),
this.rpc('eth_getTransactionCount', address, 'latest'),
this.call('eth_getBalance', address, 'latest'),
this.call('eth_getTransactionCount', address, 'latest'),
]);

@@ -374,7 +383,7 @@ balance = BigInt(balance);

async height(): Promise<number> {
return Number.parseInt(await this.rpc('eth_blockNumber'));
return Number.parseInt(await this.call('eth_blockNumber'));
}
async traceFilterSingle(address: string, opts: TraceOpts = {}) {
const res = await this.rpc('trace_filter', {
const res = await this.call('trace_filter', {
fromBlock: ethNum(opts.fromBlock),

@@ -416,3 +425,3 @@ toBlock: ethNum(opts.toBlock),

const res = await this.rpc('trace_filter', params);
const res = await this.call('trace_filter', params);
if (!res.length) break;

@@ -433,3 +442,3 @@ for (const action of res) {

if (opts.toBlock !== undefined) req.toBlock = ethNum(opts.toBlock);
const res = await this.rpc('eth_getLogs', req);
const res = await this.call('eth_getLogs', req);
return res.map((i: any) => fixLog(i, opts));

@@ -473,4 +482,4 @@ }

let [info, receipt] = await Promise.all([
this.rpc('eth_getTransactionByHash', txHash),
this.rpc('eth_getTransactionReceipt', txHash),
this.call('eth_getTransactionByHash', txHash),
this.call('eth_getTransactionReceipt', txHash),
]);

@@ -521,3 +530,3 @@ info = fixTxInfo(info);

try {
let c = createContract(ERC20, this.provider, address);
let c = createContract(ERC20, this, address);
const [symbol, decimals] = await Promise.all([c.symbol.call(), c.decimals.call()]);

@@ -657,3 +666,3 @@ return { contract: address, abi: 'ERC20', symbol, decimals: Number(decimals) };

const balances = await Promise.all(
tokens.map((i) => createContract(ERC20, this.provider, i).balanceOf.call(address))
tokens.map((i) => createContract(ERC20, this, i).balanceOf.call(address))
);

@@ -660,0 +669,0 @@ return Object.fromEntries(tokens.map((i, j) => [i, balances[j]]));

import Chainlink from './chainlink.js';
import ENS from './ens.js';
import FetchProvider from './provider.js';
import { ArchiveNodeProvider, calcTransfersDiff } from './archive.js';

@@ -9,10 +8,2 @@ import UniswapV2 from './uniswap-v2.js';

// There are many low level APIs inside which are not exported yet.
export {
ArchiveNodeProvider,
calcTransfersDiff,
Chainlink,
ENS,
FetchProvider,
UniswapV2,
UniswapV3,
};
export { ArchiveNodeProvider, calcTransfersDiff, Chainlink, ENS, UniswapV2, UniswapV3 };

@@ -13,7 +13,8 @@ import * as P from 'micro-packed';

export type BytesAccessList = [Uint8Array, Uint8Array[]][];
export declare const legacySig: P.Coder<Partial<{
type VRS = Partial<{
v: bigint;
r: bigint;
s: bigint;
}>, Partial<{
}>;
type YRS = Partial<{
chainId: bigint;

@@ -23,3 +24,4 @@ yParity: number;

s: bigint;
}>>;
}>;
export declare const legacySig: P.Coder<VRS, YRS>;
/**

@@ -26,0 +28,0 @@ * Field types, matching geth. Either u64 or u256.

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.__tests = exports.decodeLegacyV = exports.sortRawData = exports.validateFields = exports.AggregatedError = exports.RlpTx = exports.RawTx = exports.TxVersions = exports.removeSig = exports.legacySig = void 0;
exports.__tests = exports.AggregatedError = exports.RlpTx = exports.RawTx = exports.TxVersions = exports.legacySig = void 0;
exports.removeSig = removeSig;
exports.validateFields = validateFields;
exports.sortRawData = sortRawData;
exports.decodeLegacyV = decodeLegacyV;
const P = require("micro-packed");

@@ -186,3 +190,2 @@ const address_js_1 = require("./address.js");

}
exports.removeSig = removeSig;
/**

@@ -446,3 +449,2 @@ * Defines RLP transaction with fields taken from `coders`.

}
exports.validateFields = validateFields;
// prettier-ignore

@@ -465,9 +467,7 @@ const sortedFieldOrder = [

}
exports.sortRawData = sortRawData;
function decodeLegacyV(raw) {
return exports.legacySig.decode(raw).v;
}
exports.decodeLegacyV = decodeLegacyV;
// NOTE: for tests only, don't use
exports.__tests = { legacySig: exports.legacySig, TxVersions: exports.TxVersions };
//# sourceMappingURL=tx.js.map

@@ -45,3 +45,3 @@ import { isBytes as _isBytes } from '@noble/hashes/utils';

export declare function zip<A, B>(a: A[], b: B[]): [A, B][];
export declare const createDecimal: (precision: number, round?: boolean | undefined) => {
export declare const createDecimal: (precision: number, round?: boolean) => {
encode: (from: bigint) => string;

@@ -48,0 +48,0 @@ decode: (to: string) => bigint;

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.formatters = exports.gweiDecimal = exports.ethDecimal = exports.weigwei = exports.weieth = exports.createDecimal = exports.zip = exports.omit = exports.cloneDeep = exports.astr = exports.isObject = exports.hexToNumber = exports.numberTo0xHex = exports.strip0x = exports.add0x = exports.ethHexNoLeadingZero = exports.ethHex = exports.amounts = exports.isBytes = void 0;
exports.formatters = exports.gweiDecimal = exports.ethDecimal = exports.weigwei = exports.weieth = exports.createDecimal = exports.ethHexNoLeadingZero = exports.ethHex = exports.amounts = exports.isBytes = void 0;
exports.add0x = add0x;
exports.strip0x = strip0x;
exports.numberTo0xHex = numberTo0xHex;
exports.hexToNumber = hexToNumber;
exports.isObject = isObject;
exports.astr = astr;
exports.cloneDeep = cloneDeep;
exports.omit = omit;
exports.zip = zip;
const utils_1 = require("@noble/hashes/utils");

@@ -60,7 +69,5 @@ const micro_packed_1 = require("micro-packed");

}
exports.add0x = add0x;
function strip0x(hex) {
return hex.replace(ethHexStartRe, '');
}
exports.strip0x = strip0x;
function numberTo0xHex(num) {

@@ -71,3 +78,2 @@ const hex = num.toString(16);

}
exports.numberTo0xHex = numberTo0xHex;
function hexToNumber(hex) {

@@ -78,7 +84,5 @@ if (typeof hex !== 'string')

}
exports.hexToNumber = hexToNumber;
function isObject(item) {
return item != null && typeof item === 'object';
}
exports.isObject = isObject;
function astr(str) {

@@ -88,3 +92,2 @@ if (typeof str !== 'string')

}
exports.astr = astr;
function cloneDeep(obj) {

@@ -108,3 +111,2 @@ if (Array.isArray(obj)) {

}
exports.cloneDeep = cloneDeep;
function omit(obj, ...keys) {

@@ -116,3 +118,2 @@ let res = Object.assign({}, obj);

}
exports.omit = omit;
function zip(a, b) {

@@ -124,3 +125,2 @@ let res = [];

}
exports.zip = zip;
exports.createDecimal = micro_packed_1.coders.decimal;

@@ -127,0 +127,0 @@ exports.weieth = (0, exports.createDecimal)(ETH_PRECISION);

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

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc