@subsquid/evm-typegen 1.3.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +41 -3
- package/bin/run.js +1 -1
- package/lib/abi.support.d.ts +49 -0
- package/lib/abi.support.d.ts.map +1 -0
- package/lib/abi.support.js +100 -0
- package/lib/abi.support.js.map +1 -0
- package/lib/main.d.ts +1 -1
- package/lib/main.d.ts.map +1 -1
- package/lib/main.js +175 -21
- package/lib/main.js.map +1 -1
- package/lib/multicall.d.ts +31 -0
- package/lib/multicall.d.ts.map +1 -0
- package/lib/multicall.js +175 -0
- package/lib/multicall.js.map +1 -0
- package/lib/typegen.d.ts +13 -5
- package/lib/typegen.d.ts.map +1 -1
- package/lib/typegen.js +86 -254
- package/lib/typegen.js.map +1 -1
- package/lib/util/fetch.d.ts +7 -0
- package/lib/util/fetch.d.ts.map +1 -0
- package/lib/util/fetch.js +106 -0
- package/lib/util/fetch.js.map +1 -0
- package/lib/util/types.d.ts +7 -0
- package/lib/util/types.d.ts.map +1 -0
- package/lib/util/types.js +62 -0
- package/lib/util/types.js.map +1 -0
- package/package.json +11 -5
- package/src/abi.support.ts +115 -0
- package/src/main.ts +184 -24
- package/src/multicall.ts +212 -0
- package/src/typegen.ts +82 -290
- package/src/util/fetch.ts +82 -0
- package/src/util/types.ts +69 -0
package/README.md
CHANGED
|
@@ -1,5 +1,43 @@
|
|
|
1
1
|
# @subsquid/evm-typegen
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
to be used
|
|
3
|
+
Generates TypeScript facades for EVM transactions, logs and `eth_call` queries.
|
|
4
|
+
|
|
5
|
+
The generated facade classes are assumed to be used by [squids](https://docs.Subsquid.io/overview) indexing EVM data.
|
|
6
|
+
The generated classes depend on [ethers](https://www.npmjs.com/package/ethers).
|
|
7
|
+
|
|
8
|
+
## Usage
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
npm i -g @subsquid/evm-typegen
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
Arguments:
|
|
16
|
+
output-dir output directory for generated definitions
|
|
17
|
+
abi ABI file
|
|
18
|
+
|
|
19
|
+
Options:
|
|
20
|
+
--multicall generate facade for MakerDAO multicall contract
|
|
21
|
+
--etherscan-api <url> etherscan API to fetch contract ABI by a known address
|
|
22
|
+
--clean delete output directory before run
|
|
23
|
+
-h, --help display help for command
|
|
24
|
+
|
|
25
|
+
ABI file can be specified in three ways:
|
|
26
|
+
|
|
27
|
+
1. as a plain JSON file:
|
|
28
|
+
|
|
29
|
+
squid-evm-typegen src/abi erc20.json
|
|
30
|
+
|
|
31
|
+
2. as a contract address (to fetch ABI from etherscan)
|
|
32
|
+
|
|
33
|
+
squid-evm-typegen src/abi 0xBB9bc244D798123fDe783fCc1C72d3Bb8C189413
|
|
34
|
+
|
|
35
|
+
3. as an arbitrary http url
|
|
36
|
+
|
|
37
|
+
squid-evm-typegen src/abi https://example.com/erc721.json
|
|
38
|
+
|
|
39
|
+
In all cases typegen will use ABI's basename as a basename of generated files.
|
|
40
|
+
You can overwrite basename of generated files using fragment (#) suffix.
|
|
41
|
+
|
|
42
|
+
squid-evm-typegen src/abi 0xBB9bc244D798123fDe783fCc1C72d3Bb8C189413#contract
|
|
43
|
+
```
|
package/bin/run.js
CHANGED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import * as ethers from 'ethers';
|
|
2
|
+
export interface LogRecord {
|
|
3
|
+
topics: string[];
|
|
4
|
+
data: string;
|
|
5
|
+
}
|
|
6
|
+
export declare class LogEvent<Args> {
|
|
7
|
+
private abi;
|
|
8
|
+
readonly topic: string;
|
|
9
|
+
private fragment;
|
|
10
|
+
constructor(abi: ethers.utils.Interface, topic: string);
|
|
11
|
+
decode(rec: LogRecord): Args;
|
|
12
|
+
}
|
|
13
|
+
export declare class Func<Args extends any[], FieldArgs, Result> {
|
|
14
|
+
private abi;
|
|
15
|
+
readonly sighash: string;
|
|
16
|
+
private fragment;
|
|
17
|
+
constructor(abi: ethers.utils.Interface, sighash: string);
|
|
18
|
+
decode(input: ethers.utils.BytesLike): Args & FieldArgs;
|
|
19
|
+
encode(args: Args): string;
|
|
20
|
+
decodeResult(output: ethers.utils.BytesLike): Result;
|
|
21
|
+
tryDecodeResult(output: ethers.utils.BytesLike): Result | undefined;
|
|
22
|
+
}
|
|
23
|
+
export declare function isFunctionResultDecodingError(val: unknown): val is Error & {
|
|
24
|
+
data: string;
|
|
25
|
+
};
|
|
26
|
+
export interface ChainContext {
|
|
27
|
+
_chain: Chain;
|
|
28
|
+
}
|
|
29
|
+
export interface BlockContext {
|
|
30
|
+
_chain: Chain;
|
|
31
|
+
block: Block;
|
|
32
|
+
}
|
|
33
|
+
export interface Block {
|
|
34
|
+
height: number;
|
|
35
|
+
}
|
|
36
|
+
export interface Chain {
|
|
37
|
+
client: {
|
|
38
|
+
call: <T = any>(method: string, params?: unknown[]) => Promise<T>;
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
export declare class ContractBase {
|
|
42
|
+
private readonly _chain;
|
|
43
|
+
private readonly blockHeight;
|
|
44
|
+
readonly address: string;
|
|
45
|
+
constructor(ctx: BlockContext, address: string);
|
|
46
|
+
constructor(ctx: ChainContext, block: Block, address: string);
|
|
47
|
+
eth_call<Args extends any[], FieldArgs, Result>(func: Func<Args, FieldArgs, Result>, args: Args): Promise<Result>;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=abi.support.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"abi.support.d.ts","sourceRoot":"","sources":["../src/abi.support.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAA;AAGhC,MAAM,WAAW,SAAS;IACtB,MAAM,EAAE,MAAM,EAAE,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;CACf;AAGD,qBAAa,QAAQ,CAAC,IAAI;IAGV,OAAO,CAAC,GAAG;aAA0C,KAAK,EAAE,MAAM;IAF9E,OAAO,CAAC,QAAQ,CAA4B;gBAExB,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,SAAS,EAAkB,KAAK,EAAE,MAAM;IAI9E,MAAM,CAAC,GAAG,EAAE,SAAS,GAAG,IAAI;CAG/B;AAGD,qBAAa,IAAI,CAAC,IAAI,SAAS,GAAG,EAAE,EAAE,SAAS,EAAE,MAAM;IAGvC,OAAO,CAAC,GAAG;aAA0C,OAAO,EAAE,MAAM;IAFhF,OAAO,CAAC,QAAQ,CAA+B;gBAE3B,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,SAAS,EAAkB,OAAO,EAAE,MAAM;IAIhF,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,SAAS,GAAG,IAAI,GAAG,SAAS;IAIvD,MAAM,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM;IAI1B,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,SAAS,GAAG,MAAM;IAKpD,eAAe,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,SAAS,GAAG,MAAM,GAAG,SAAS;CAOtE;AAGD,wBAAgB,6BAA6B,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,KAAK,GAAG;IAAC,IAAI,EAAE,MAAM,CAAA;CAAC,CAOzF;AAGD,MAAM,WAAW,YAAY;IACzB,MAAM,EAAE,KAAK,CAAA;CAChB;AAGD,MAAM,WAAW,YAAY;IACzB,MAAM,EAAE,KAAK,CAAA;IACb,KAAK,EAAE,KAAK,CAAA;CACf;AAGD,MAAM,WAAW,KAAK;IAClB,MAAM,EAAE,MAAM,CAAA;CACjB;AAGD,MAAM,WAAW,KAAK;IAClB,MAAM,EAAG;QACL,IAAI,EAAE,CAAC,CAAC,GAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,CAAC,CAAC,CAAA;KAClE,CAAA;CACJ;AAGD,qBAAa,YAAY;IACrB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAO;IAC9B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAQ;IACpC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;gBAEZ,GAAG,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM;gBAClC,GAAG,EAAE,YAAY,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM;IAetD,QAAQ,CAAC,IAAI,SAAS,GAAG,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC;CAQ1H"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.ContractBase = exports.isFunctionResultDecodingError = exports.Func = exports.LogEvent = void 0;
|
|
27
|
+
const ethers = __importStar(require("ethers"));
|
|
28
|
+
class LogEvent {
|
|
29
|
+
constructor(abi, topic) {
|
|
30
|
+
this.abi = abi;
|
|
31
|
+
this.topic = topic;
|
|
32
|
+
this.fragment = abi.getEvent(topic);
|
|
33
|
+
}
|
|
34
|
+
decode(rec) {
|
|
35
|
+
return this.abi.decodeEventLog(this.fragment, rec.data, rec.topics);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
exports.LogEvent = LogEvent;
|
|
39
|
+
class Func {
|
|
40
|
+
constructor(abi, sighash) {
|
|
41
|
+
this.abi = abi;
|
|
42
|
+
this.sighash = sighash;
|
|
43
|
+
this.fragment = abi.getFunction(sighash);
|
|
44
|
+
}
|
|
45
|
+
decode(input) {
|
|
46
|
+
return this.abi.decodeFunctionData(this.fragment, input);
|
|
47
|
+
}
|
|
48
|
+
encode(args) {
|
|
49
|
+
return this.abi.encodeFunctionData(this.fragment, args);
|
|
50
|
+
}
|
|
51
|
+
decodeResult(output) {
|
|
52
|
+
const decoded = this.abi.decodeFunctionResult(this.fragment, output);
|
|
53
|
+
return decoded.length > 1 ? decoded : decoded[0];
|
|
54
|
+
}
|
|
55
|
+
tryDecodeResult(output) {
|
|
56
|
+
try {
|
|
57
|
+
return this.decodeResult(output);
|
|
58
|
+
}
|
|
59
|
+
catch (err) {
|
|
60
|
+
return undefined;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
exports.Func = Func;
|
|
65
|
+
function isFunctionResultDecodingError(val) {
|
|
66
|
+
if (!(val instanceof Error))
|
|
67
|
+
return false;
|
|
68
|
+
let err = val;
|
|
69
|
+
return err.code == 'CALL_EXCEPTION'
|
|
70
|
+
&& typeof err.data == 'string'
|
|
71
|
+
&& !err.errorArgs
|
|
72
|
+
&& !err.errorName;
|
|
73
|
+
}
|
|
74
|
+
exports.isFunctionResultDecodingError = isFunctionResultDecodingError;
|
|
75
|
+
class ContractBase {
|
|
76
|
+
constructor(ctx, blockOrAddress, address) {
|
|
77
|
+
this._chain = ctx._chain;
|
|
78
|
+
if (typeof blockOrAddress === 'string') {
|
|
79
|
+
this.blockHeight = ctx.block.height;
|
|
80
|
+
this.address = ethers.utils.getAddress(blockOrAddress);
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
if (address == null) {
|
|
84
|
+
throw new Error('missing contract address');
|
|
85
|
+
}
|
|
86
|
+
this.blockHeight = blockOrAddress.height;
|
|
87
|
+
this.address = ethers.utils.getAddress(address);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
async eth_call(func, args) {
|
|
91
|
+
let data = func.encode(args);
|
|
92
|
+
let result = await this._chain.client.call('eth_call', [
|
|
93
|
+
{ to: this.address, data },
|
|
94
|
+
'0x' + this.blockHeight.toString(16)
|
|
95
|
+
]);
|
|
96
|
+
return func.decodeResult(result);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
exports.ContractBase = ContractBase;
|
|
100
|
+
//# sourceMappingURL=abi.support.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"abi.support.js","sourceRoot":"","sources":["../src/abi.support.ts"],"names":[],"mappings":"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"}
|
package/lib/main.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export
|
|
1
|
+
export {};
|
|
2
2
|
//# sourceMappingURL=main.d.ts.map
|
package/lib/main.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":""}
|
package/lib/main.js
CHANGED
|
@@ -1,37 +1,191 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
2
25
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
26
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
27
|
};
|
|
5
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
|
|
29
|
+
const abi_1 = require("@ethersproject/abi");
|
|
30
|
+
const address_1 = require("@ethersproject/address");
|
|
31
|
+
const logger_1 = require("@subsquid/logger");
|
|
32
|
+
const util_internal_1 = require("@subsquid/util-internal");
|
|
33
|
+
const util_internal_code_printer_1 = require("@subsquid/util-internal-code-printer");
|
|
34
|
+
const validator = __importStar(require("@subsquid/util-internal-commander"));
|
|
7
35
|
const commander_1 = require("commander");
|
|
36
|
+
const fs = __importStar(require("fs"));
|
|
8
37
|
const path_1 = __importDefault(require("path"));
|
|
9
|
-
const process_1 = __importDefault(require("process"));
|
|
10
38
|
const typegen_1 = require("./typegen");
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
39
|
+
const fetch_1 = require("./util/fetch");
|
|
40
|
+
const LOG = (0, logger_1.createLogger)('sqd:evm-typegen');
|
|
41
|
+
(0, util_internal_1.runProgram)(async function () {
|
|
42
|
+
commander_1.program
|
|
43
|
+
.description(`
|
|
44
|
+
Generates TypeScript facades for EVM transactions, logs and eth_call queries.
|
|
45
|
+
|
|
46
|
+
The generated facades are assumed to be used by "squids" indexing EVM data.
|
|
15
47
|
`.trim())
|
|
16
|
-
.
|
|
17
|
-
.
|
|
48
|
+
.name('squid-evm-typegen')
|
|
49
|
+
.argument('<output-dir>', 'output directory for generated definitions')
|
|
50
|
+
.argument('[abi...]', 'ABI file', specArgument)
|
|
51
|
+
.option('--multicall', 'generate facade for MakerDAO multicall contract')
|
|
52
|
+
.option('--etherscan-api <url>', 'etherscan API to fetch contract ABI by a known address', validator.Url(['http:', 'https:']))
|
|
53
|
+
.option('--clean', 'delete output directory before run')
|
|
54
|
+
.addHelpText('afterAll', `
|
|
55
|
+
ABI file can be specified in three ways:
|
|
56
|
+
|
|
57
|
+
1. as a plain JSON file:
|
|
58
|
+
|
|
59
|
+
squid-evm-typegen src/abi erc20.json
|
|
60
|
+
|
|
61
|
+
2. as a contract address (to fetch ABI from etherscan)
|
|
62
|
+
|
|
63
|
+
squid-evm-typegen src/abi 0xBB9bc244D798123fDe783fCc1C72d3Bb8C189413
|
|
64
|
+
|
|
65
|
+
3. as an arbitrary http url
|
|
66
|
+
|
|
67
|
+
squid-evm-typegen src/abi https://example.com/erc721.json
|
|
68
|
+
|
|
69
|
+
In all cases typegen will use ABI's basename as a basename of generated files.
|
|
70
|
+
You can overwrite basename of generated files using fragment (#) suffix.
|
|
71
|
+
|
|
72
|
+
squid-evm-typegen src/abi 0xBB9bc244D798123fDe783fCc1C72d3Bb8C189413#contract
|
|
73
|
+
`);
|
|
18
74
|
commander_1.program.parse();
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
if (
|
|
23
|
-
|
|
75
|
+
let opts = commander_1.program.opts();
|
|
76
|
+
let dest = new util_internal_code_printer_1.OutDir(commander_1.program.processedArgs[0]);
|
|
77
|
+
let specs = commander_1.program.processedArgs[1];
|
|
78
|
+
if (opts.clean && dest.exists()) {
|
|
79
|
+
LOG.info(`deleting ${dest.path()}`);
|
|
80
|
+
dest.del();
|
|
81
|
+
}
|
|
82
|
+
if (specs.length == 0 && !opts.multicall) {
|
|
83
|
+
LOG.warn('no ABI files given, nothing to generate');
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
dest.add('abi.support.ts', [__dirname, '../src/abi.support.ts']);
|
|
87
|
+
LOG.info(`saved ${dest.path('abi.support.ts')}`);
|
|
88
|
+
if (opts.multicall) {
|
|
89
|
+
dest.add('multicall.ts', [__dirname, '../src/multicall.ts']);
|
|
90
|
+
LOG.info(`saved ${dest.path('multicall.ts')}`);
|
|
91
|
+
}
|
|
92
|
+
for (let spec of specs) {
|
|
93
|
+
LOG.info(`processing ${spec.src}`);
|
|
94
|
+
let abi_json = await read(spec, opts);
|
|
95
|
+
let abi = new abi_1.Interface(abi_json);
|
|
96
|
+
new typegen_1.Typegen(dest, abi, spec.name, LOG).generate();
|
|
97
|
+
}
|
|
98
|
+
}, err => LOG.fatal(err));
|
|
99
|
+
async function read(spec, options) {
|
|
100
|
+
if (spec.kind == 'address') {
|
|
101
|
+
return fetchFromEtherscan(spec.src, options?.etherscanApi);
|
|
24
102
|
}
|
|
25
|
-
|
|
26
|
-
|
|
103
|
+
let abi;
|
|
104
|
+
if (spec.kind == 'url') {
|
|
105
|
+
abi = await (0, fetch_1.GET)(spec.src);
|
|
27
106
|
}
|
|
28
|
-
|
|
29
|
-
|
|
107
|
+
else {
|
|
108
|
+
abi = JSON.parse(fs.readFileSync(spec.src, 'utf-8'));
|
|
109
|
+
}
|
|
110
|
+
if (Array.isArray(abi)) {
|
|
111
|
+
return abi;
|
|
112
|
+
}
|
|
113
|
+
else if (Array.isArray(abi?.abi)) {
|
|
114
|
+
return abi.abi;
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
throw new Error('Unrecognized ABI format');
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
async function fetchFromEtherscan(address, api) {
|
|
121
|
+
api = api || 'https://api.etherscan.io/';
|
|
122
|
+
let url = new URL('api?module=contract&action=getabi', api);
|
|
123
|
+
url.searchParams.set('address', address);
|
|
124
|
+
let response;
|
|
125
|
+
let attempts = 2;
|
|
126
|
+
while (true) {
|
|
127
|
+
response = await (0, fetch_1.GET)(url.toString());
|
|
128
|
+
if (response.status == '0' && response.result.includes('rate limit') && --attempts) {
|
|
129
|
+
LOG.warn('faced rate limit error while trying to fetch contract ABI. Trying again in 2 seconds.');
|
|
130
|
+
await (0, util_internal_1.wait)(2000);
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
break;
|
|
134
|
+
}
|
|
30
135
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
process_1.default.exit(1);
|
|
136
|
+
if (response.status == '1') {
|
|
137
|
+
return JSON.parse(response.result);
|
|
34
138
|
}
|
|
139
|
+
else {
|
|
140
|
+
throw new Error(`Failed to fetch contract ABI from ${api}: ${response.result}`);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
function specArgument(value, prev) {
|
|
144
|
+
let spec = parseSpec(value);
|
|
145
|
+
prev.push(spec);
|
|
146
|
+
return prev;
|
|
147
|
+
}
|
|
148
|
+
function parseSpec(spec) {
|
|
149
|
+
let [src, fragment] = splitFragment(spec);
|
|
150
|
+
if (src.startsWith('0x')) {
|
|
151
|
+
if (!(0, address_1.isAddress)(src))
|
|
152
|
+
throw new commander_1.InvalidArgumentError('Invalid contract address');
|
|
153
|
+
return {
|
|
154
|
+
kind: 'address',
|
|
155
|
+
src,
|
|
156
|
+
name: fragment || src
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
else if (src.includes('://')) {
|
|
160
|
+
let u = new URL(validator.Url(['http:', 'https:'])(src));
|
|
161
|
+
return {
|
|
162
|
+
kind: 'url',
|
|
163
|
+
src,
|
|
164
|
+
name: fragment || basename(u.pathname)
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
return {
|
|
169
|
+
kind: 'file',
|
|
170
|
+
src,
|
|
171
|
+
name: fragment || basename(src)
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
function splitFragment(spec) {
|
|
176
|
+
let parts = spec.split('#');
|
|
177
|
+
if (parts.length > 1) {
|
|
178
|
+
let fragment = parts.pop();
|
|
179
|
+
return [parts.join('#'), fragment];
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
return [spec, ''];
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
function basename(file) {
|
|
186
|
+
let name = path_1.default.parse(file).name;
|
|
187
|
+
if (name)
|
|
188
|
+
return name;
|
|
189
|
+
throw new commander_1.InvalidArgumentError(`Can't derive target basename for output files. Use url fragment to specify it, e.g. #erc20`);
|
|
35
190
|
}
|
|
36
|
-
exports.run = run;
|
|
37
191
|
//# sourceMappingURL=main.js.map
|
package/lib/main.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import * as ethers from 'ethers';
|
|
2
|
+
import { ContractBase, Func } from './abi.support';
|
|
3
|
+
declare type AnyFunc = Func<any, {}, any>;
|
|
4
|
+
declare type Call = [address: string, bytes: string];
|
|
5
|
+
export declare type MulticallResult<T> = {
|
|
6
|
+
success: true;
|
|
7
|
+
value: T;
|
|
8
|
+
} | {
|
|
9
|
+
success: false;
|
|
10
|
+
returnData?: string;
|
|
11
|
+
value?: undefined;
|
|
12
|
+
};
|
|
13
|
+
export declare class Multicall extends ContractBase {
|
|
14
|
+
static aggregate: Func<[calls: Call[]], {}, {
|
|
15
|
+
blockNumber: ethers.ethers.BigNumber;
|
|
16
|
+
returnData: string[];
|
|
17
|
+
}>;
|
|
18
|
+
static try_aggregate: Func<[requireSuccess: boolean, calls: [target: string, callData: string][]], {}, {
|
|
19
|
+
success: boolean;
|
|
20
|
+
returnData: string;
|
|
21
|
+
}[]>;
|
|
22
|
+
aggregate<Args extends any[], R>(func: Func<Args, {}, R>, address: string, calls: Args[], paging?: number): Promise<R[]>;
|
|
23
|
+
aggregate<Args extends any[], R>(func: Func<Args, {}, R>, calls: [address: string, args: Args][], paging?: number): Promise<R[]>;
|
|
24
|
+
aggregate(calls: [func: AnyFunc, address: string, args: any[]][], paging?: number): Promise<any[]>;
|
|
25
|
+
tryAggregate<Args extends any[], R>(func: Func<Args, {}, R>, address: string, calls: Args[], paging?: number): Promise<MulticallResult<R>[]>;
|
|
26
|
+
tryAggregate<Args extends any[], R>(func: Func<Args, {}, R>, calls: [address: string, args: Args][], paging?: number): Promise<MulticallResult<R>[]>;
|
|
27
|
+
tryAggregate(calls: [func: AnyFunc, address: string, args: any[]][], paging?: number): Promise<MulticallResult<any>[]>;
|
|
28
|
+
private makeCalls;
|
|
29
|
+
}
|
|
30
|
+
export {};
|
|
31
|
+
//# sourceMappingURL=multicall.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"multicall.d.ts","sourceRoot":"","sources":["../src/multicall.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAA;AAChC,OAAO,EAAC,YAAY,EAAE,IAAI,EAAC,MAAM,eAAe,CAAA;AAoDhD,aAAK,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,EAAE,EAAE,GAAG,CAAC,CAAA;AACjC,aAAK,IAAI,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,CAAA;AAa5C,oBAAY,eAAe,CAAC,CAAC,IAAI;IAC7B,OAAO,EAAE,IAAI,CAAA;IACb,KAAK,EAAE,CAAC,CAAA;CACX,GAAG;IACA,OAAO,EAAE,KAAK,CAAA;IACd,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,KAAK,CAAC,EAAE,SAAS,CAAA;CACpB,CAAA;AAGD,qBAAa,SAAU,SAAQ,YAAY;IACvC,MAAM,CAAC,SAAS;;;OAAY;IAC5B,MAAM,CAAC,aAAa;;;SAAgB;IAEpC,SAAS,CAAC,IAAI,SAAS,GAAG,EAAE,EAAE,CAAC,EAC3B,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,EACvB,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,IAAI,EAAE,EACb,MAAM,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,CAAC,EAAE,CAAC;IAEf,SAAS,CAAC,IAAI,SAAS,GAAG,EAAE,EAAE,CAAC,EAC3B,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,EACvB,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,EACtC,MAAM,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,CAAC,EAAE,CAAC;IAEf,SAAS,CACL,KAAK,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,EAAE,EACtD,MAAM,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,GAAG,EAAE,CAAC;IAgBjB,YAAY,CAAC,IAAI,SAAS,GAAG,EAAE,EAAE,CAAC,EAC9B,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,EACvB,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,IAAI,EAAE,EACb,MAAM,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE,CAAC;IAEhC,YAAY,CAAC,IAAI,SAAS,GAAG,EAAE,EAAE,CAAC,EAC9B,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,EACvB,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,EACtC,MAAM,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE,CAAC;IAEhC,YAAY,CACR,KAAK,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,EAAE,EACtD,MAAM,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,eAAe,CAAC,GAAG,CAAC,EAAE,CAAC;IA2BlC,OAAO,CAAC,SAAS;CA2CpB"}
|
package/lib/multicall.js
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.Multicall = void 0;
|
|
27
|
+
const ethers = __importStar(require("ethers"));
|
|
28
|
+
const abi_support_1 = require("./abi.support");
|
|
29
|
+
const abi = new ethers.utils.Interface([
|
|
30
|
+
{
|
|
31
|
+
type: 'function',
|
|
32
|
+
name: 'aggregate',
|
|
33
|
+
stateMutability: 'nonpayable',
|
|
34
|
+
inputs: [
|
|
35
|
+
{
|
|
36
|
+
name: 'calls',
|
|
37
|
+
type: 'tuple[]',
|
|
38
|
+
components: [
|
|
39
|
+
{ name: 'target', type: 'address' },
|
|
40
|
+
{ name: 'callData', type: 'bytes' },
|
|
41
|
+
]
|
|
42
|
+
}
|
|
43
|
+
],
|
|
44
|
+
outputs: [
|
|
45
|
+
{ name: 'blockNumber', type: 'uint256' },
|
|
46
|
+
{ name: 'returnData', type: 'bytes[]' },
|
|
47
|
+
]
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
name: 'tryAggregate',
|
|
51
|
+
type: 'function',
|
|
52
|
+
stateMutability: 'nonpayable',
|
|
53
|
+
inputs: [
|
|
54
|
+
{ name: 'requireSuccess', type: 'bool' },
|
|
55
|
+
{
|
|
56
|
+
name: 'calls',
|
|
57
|
+
type: 'tuple[]',
|
|
58
|
+
components: [
|
|
59
|
+
{ name: 'target', type: 'address' },
|
|
60
|
+
{ name: 'callData', type: 'bytes' },
|
|
61
|
+
]
|
|
62
|
+
}
|
|
63
|
+
],
|
|
64
|
+
outputs: [
|
|
65
|
+
{
|
|
66
|
+
name: 'returnData',
|
|
67
|
+
type: 'tuple[]',
|
|
68
|
+
components: [
|
|
69
|
+
{ name: 'success', type: 'bool' },
|
|
70
|
+
{ name: 'returnData', type: 'bytes' },
|
|
71
|
+
]
|
|
72
|
+
},
|
|
73
|
+
]
|
|
74
|
+
}
|
|
75
|
+
]);
|
|
76
|
+
const aggregate = new abi_support_1.Func(abi, abi.getSighash('aggregate'));
|
|
77
|
+
const try_aggregate = new abi_support_1.Func(abi, abi.getSighash('tryAggregate'));
|
|
78
|
+
class Multicall extends abi_support_1.ContractBase {
|
|
79
|
+
async aggregate(...args) {
|
|
80
|
+
let [calls, funcs, page] = this.makeCalls(args);
|
|
81
|
+
let size = calls.length;
|
|
82
|
+
let results = new Array(size);
|
|
83
|
+
for (let [from, to] of splitIntoPages(size, page)) {
|
|
84
|
+
let { returnData } = await this.eth_call(aggregate, [calls.slice(from, to)]);
|
|
85
|
+
for (let i = from; i < to; i++) {
|
|
86
|
+
let data = returnData[i - from];
|
|
87
|
+
results[i] = funcs[i].decodeResult(data);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return results;
|
|
91
|
+
}
|
|
92
|
+
async tryAggregate(...args) {
|
|
93
|
+
let [calls, funcs, page] = this.makeCalls(args);
|
|
94
|
+
let size = calls.length;
|
|
95
|
+
let results = new Array(size);
|
|
96
|
+
for (let [from, to] of splitIntoPages(size, page)) {
|
|
97
|
+
let response = await this.eth_call(try_aggregate, [false, calls.slice(from, to)]);
|
|
98
|
+
for (let i = from; i < to; i++) {
|
|
99
|
+
let res = response[i - from];
|
|
100
|
+
if (res.success) {
|
|
101
|
+
try {
|
|
102
|
+
results[i] = {
|
|
103
|
+
success: true,
|
|
104
|
+
value: funcs[i].decodeResult(res.returnData)
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
catch (err) {
|
|
108
|
+
results[i] = { success: false, returnData: res.returnData };
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
results[i] = { success: false };
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return results;
|
|
117
|
+
}
|
|
118
|
+
makeCalls(args) {
|
|
119
|
+
let page = typeof args[args.length - 1] == 'number' ? args.pop() : Number.MAX_SAFE_INTEGER;
|
|
120
|
+
switch (args.length) {
|
|
121
|
+
case 1: {
|
|
122
|
+
let list = args[0];
|
|
123
|
+
let calls = new Array(list.length);
|
|
124
|
+
let funcs = new Array(list.length);
|
|
125
|
+
for (let i = 0; i < list.length; i++) {
|
|
126
|
+
let [func, address, args] = list[i];
|
|
127
|
+
calls[i] = [address, func.encode(args)];
|
|
128
|
+
funcs[i] = func;
|
|
129
|
+
}
|
|
130
|
+
return [calls, funcs, page];
|
|
131
|
+
}
|
|
132
|
+
case 2: {
|
|
133
|
+
let func = args[0];
|
|
134
|
+
let list = args[1];
|
|
135
|
+
let calls = new Array(list.length);
|
|
136
|
+
let funcs = new Array(list.length);
|
|
137
|
+
for (let i = 0; i < list.length; i++) {
|
|
138
|
+
let [address, args] = list[i];
|
|
139
|
+
calls[i] = [address, func.encode(args)];
|
|
140
|
+
funcs[i] = func;
|
|
141
|
+
}
|
|
142
|
+
return [calls, funcs, page];
|
|
143
|
+
}
|
|
144
|
+
case 3: {
|
|
145
|
+
let func = args[0];
|
|
146
|
+
let address = args[1];
|
|
147
|
+
let list = args[2];
|
|
148
|
+
let calls = new Array(list.length);
|
|
149
|
+
let funcs = new Array(list.length);
|
|
150
|
+
for (let i = 0; i < list.length; i++) {
|
|
151
|
+
let args = list[i];
|
|
152
|
+
calls[i] = [address, func.encode(args)];
|
|
153
|
+
funcs[i] = func;
|
|
154
|
+
}
|
|
155
|
+
return [calls, funcs, page];
|
|
156
|
+
}
|
|
157
|
+
default:
|
|
158
|
+
throw new Error('unexpected number of arguments');
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
exports.Multicall = Multicall;
|
|
163
|
+
Multicall.aggregate = aggregate;
|
|
164
|
+
Multicall.try_aggregate = try_aggregate;
|
|
165
|
+
function* splitIntoPages(size, page) {
|
|
166
|
+
let from = 0;
|
|
167
|
+
while (size) {
|
|
168
|
+
let step = Math.min(page, size);
|
|
169
|
+
let to = from + step;
|
|
170
|
+
yield [from, to];
|
|
171
|
+
size -= step;
|
|
172
|
+
from = to;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
//# sourceMappingURL=multicall.js.map
|