Merge pull request #2 from ethers-io/ethers-v5-beta
Ethers v5 beta Update
This commit is contained in:
commit
8d27286be1
4
.gitignore
vendored
4
.gitignore
vendored
@ -14,3 +14,7 @@ shims/*.d.ts
|
||||
**/*.tmp-browserify-*
|
||||
|
||||
lerna-debug.log
|
||||
|
||||
packages/*/tsconfig.tsbuildinfo
|
||||
|
||||
packages/testcases/input/nameprep/**
|
||||
|
14
CHANGELOG.md
14
CHANGELOG.md
@ -3,6 +3,20 @@ Changelog
|
||||
|
||||
This change log is managed by `scripts/cmds/update-versions` but may be manually updated.
|
||||
|
||||
ethers/v5.0.0-beta.156 (2019-09-06 17:56)
|
||||
-----------------------------------------
|
||||
|
||||
- Removed export star to fix UMD dist file. ([4c17c4d](https://github.com/ethers-io/ethers.js/commit/4c17c4db0455e1b89fd597c4c929cdc36aa3d90d))
|
||||
- Updated TypeScript version. ([e8028d0](https://github.com/ethers-io/ethers.js/commit/e8028d0e73368257b76b394bb8e2bf63f8aecd71))
|
||||
- Fixed test suites and reporter. ([1e0ed4e](https://github.com/ethers-io/ethers.js/commit/1e0ed4e99a22a27fe5057336f8cb320809768f3e))
|
||||
- Added lock-versions admin tool. ([2187604](https://github.com/ethers-io/ethers.js/commit/21876049137644af2b3afa31120ee95d032843a8))
|
||||
- Updated packages with version lock and moved types. ([85b4db7](https://github.com/ethers-io/ethers.js/commit/85b4db7d6db37b853f11a90cf4648c34404edcf9))
|
||||
- Fixed typo in error message. ([#592](https://github.com/ethers-io/ethers.js/issues/592); [019c1fc](https://github.com/ethers-io/ethers.js/commit/019c1fc7089b3da2d7bd41c933b6c6bc35c8dade))
|
||||
- Fixed build process to re-target browser field to ES version. ([3a91e91](https://github.com/ethers-io/ethers.js/commit/3a91e91df56c1ef6cf096c0322f74fd5060891e0))
|
||||
- Major overhaul in compilation to enable ES6 module generation. ([73a0077](https://github.com/ethers-io/ethers.js/commit/73a0077fd38c6ae79f33a9d4d3cc128a904b4a6c))
|
||||
- Updated some of the flatworm docs. ([81fd942](https://github.com/ethers-io/ethers.js/commit/81fd9428cab4be7eee7ddeb564bf91f282cae475))
|
||||
- Fixed package descriptions. ([#561](https://github.com/ethers-io/ethers.js/issues/561); [ebfca98](https://github.com/ethers-io/ethers.js/commit/ebfca98dc276d6f6ca6961632635e8203bb17645))
|
||||
|
||||
ethers/v5.0.0-beta.155 (2019-08-22 17:11)
|
||||
-----------------------------------------
|
||||
|
||||
|
@ -4,7 +4,9 @@ const fs = require("fs");
|
||||
const resolve = require("path").resolve;
|
||||
const spawn = require("child_process").spawn;
|
||||
|
||||
const local = require("./local");
|
||||
const { dirnames } = require("./local");
|
||||
const { loadPackage, savePackage } = require("./local");
|
||||
const { loadJson, saveJson } = require("./utils");
|
||||
|
||||
function run(progname, args, ignoreErrorStream) {
|
||||
return new Promise((resolve, reject) => {
|
||||
@ -46,16 +48,67 @@ function run(progname, args, ignoreErrorStream) {
|
||||
});
|
||||
}
|
||||
|
||||
function runBuild() {
|
||||
return run("npx", [ "tsc", "--build", resolve(__dirname, "../tsconfig.project.json") ]);
|
||||
function setupConfig(outDir, moduleType, targetType) {
|
||||
function update(value) {
|
||||
let comps = value.split("/");
|
||||
if (comps.length >= 3 && comps[0] === "." && comps[1].match(/^lib(\.esm)?$/)) {
|
||||
return outDir + comps.slice(2).join("/");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
// Configure the tsconfit.package.json...
|
||||
const path = resolve(__dirname, "../tsconfig.package.json");
|
||||
const content = loadJson(path);
|
||||
content.compilerOptions.module = moduleType;
|
||||
content.compilerOptions.target = targetType;
|
||||
saveJson(path, content);
|
||||
|
||||
dirnames.forEach((dirname) => {
|
||||
let info = loadPackage(dirname);
|
||||
|
||||
if (info._ethers_nobuild) { return; }
|
||||
|
||||
if (info.browser) {
|
||||
if (typeof(info.browser) === "string") {
|
||||
info.browser = update(info.browser);
|
||||
} else {
|
||||
for (let key in info.browser) {
|
||||
info.browser[key] = update(info.browser[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
savePackage(dirname, info);
|
||||
|
||||
let path = resolve(__dirname, "../packages", dirname, "tsconfig.json");
|
||||
let content = loadJson(path);
|
||||
content.compilerOptions.outDir = outDir;
|
||||
saveJson(path, content);
|
||||
});
|
||||
}
|
||||
|
||||
function setupBuild(buildModule) {
|
||||
if (buildModule) {
|
||||
setupConfig("./lib.esm/", "es2015", "es2015");
|
||||
} else {
|
||||
setupConfig("./lib/", "commonjs", "es5");
|
||||
}
|
||||
}
|
||||
|
||||
function runBuild(buildModule) {
|
||||
setupBuild(buildModule);
|
||||
|
||||
// Compile
|
||||
return run("npx", [ "tsc", "--build", resolve(__dirname, "../tsconfig.project.json"), "--force" ]);
|
||||
}
|
||||
|
||||
function runDist() {
|
||||
return run("npx", [ "lerna", "run", "dist" ], true);
|
||||
return run("npm", [ "run", "_dist_ethers" ], true);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
run: run,
|
||||
runDist: runDist,
|
||||
runBuild: runBuild
|
||||
runBuild: runBuild,
|
||||
setupBuild: setupBuild
|
||||
};
|
||||
|
41
admin/cmds/lock-versions.js
Normal file
41
admin/cmds/lock-versions.js
Normal file
@ -0,0 +1,41 @@
|
||||
"use strict";
|
||||
|
||||
const { getOrdered, loadPackage } = require("../depgraph");
|
||||
const { savePackage } = require("../local");
|
||||
const { log } = require("../log");
|
||||
|
||||
(async function() {
|
||||
let versions = { };
|
||||
|
||||
const dirnames = getOrdered();
|
||||
|
||||
dirnames.forEach((dirname) => {
|
||||
let info = loadPackage(dirname);
|
||||
if (info.name.split("/")[0] === "@ethersproject" || info.name === "ethers") {
|
||||
versions[info.name] = info.version;
|
||||
}
|
||||
});
|
||||
|
||||
dirnames.forEach((dirname) => {
|
||||
const info = loadPackage(dirname);
|
||||
let shown = false;
|
||||
["dependencies", "devDependencies"].forEach((key) => {
|
||||
const deps = info[key];
|
||||
if (!deps) { return; }
|
||||
Object.keys(deps).forEach((name) => {
|
||||
if (versions[name] == null) { return; }
|
||||
const value = ">=" + versions[name];
|
||||
if (value !== deps[name])
|
||||
if (!deps[name]) { return; }
|
||||
if (!shown) {
|
||||
log(`<bold:Locking ${ info.name }:>`);
|
||||
shown = true;
|
||||
}
|
||||
log(` <green:${ name }>: ${ deps[name] } => <bold:${ value.substring(2) }>`);
|
||||
deps[name] = value;
|
||||
});
|
||||
});
|
||||
savePackage(dirname, info);
|
||||
});
|
||||
|
||||
})();
|
5
admin/cmds/reset-build.js
Normal file
5
admin/cmds/reset-build.js
Normal file
@ -0,0 +1,5 @@
|
||||
"use strict";
|
||||
|
||||
const { setupBuild } = require("../build");
|
||||
|
||||
setupBuild(false);
|
20
admin/cmds/update-exports.js
Normal file
20
admin/cmds/update-exports.js
Normal file
@ -0,0 +1,20 @@
|
||||
"use strict";
|
||||
|
||||
const fs = require("fs");
|
||||
const { resolve } = require("path");
|
||||
|
||||
const sourceEthers = fs.readFileSync(resolve(__dirname, "../../packages/ethers/src.ts/ethers.ts")).toString();
|
||||
const targets = sourceEthers.match(/export\s*{\s*((.|\s)*)}/)[1].trim();
|
||||
|
||||
const output = `"use strict";
|
||||
|
||||
import * as ethers from "./ethers";
|
||||
|
||||
export { ethers };
|
||||
|
||||
export {
|
||||
${ targets }
|
||||
} from "./ethers";
|
||||
`;
|
||||
|
||||
fs.writeFileSync(resolve(__dirname, "../../packages/ethers/src.ts/index.ts"), output);
|
@ -18,7 +18,7 @@ const { getPackageVersion } = require("../npm");
|
||||
const { resolve } = require("../utils");
|
||||
const { colorify, log } = require("../log");
|
||||
|
||||
const { getProgressBar } = require("../../packages/cli/prompt");
|
||||
const { prompt } = require("../../packages/cli");
|
||||
|
||||
let dirnames = getOrdered();
|
||||
|
||||
@ -41,8 +41,7 @@ if (process.argv.length > 2) {
|
||||
}
|
||||
|
||||
(async function() {
|
||||
|
||||
let progress = getProgressBar(colorify("Updating versions", "bold"));
|
||||
let progress = prompt.getProgressBar(colorify("Updating versions", "bold"));
|
||||
|
||||
for (let i = 0; i < dirnames.length; i++) {
|
||||
progress(i / dirnames.length);
|
||||
@ -52,14 +51,6 @@ if (process.argv.length > 2) {
|
||||
|
||||
// Get local package.json (update the tarballHash)
|
||||
let info = await updatePackage(dirname);
|
||||
/*
|
||||
let info = await updatePackage(dirname, {
|
||||
repository: {
|
||||
type: "git",
|
||||
url: "git://github.com/ethers-io/ethers.js.git"
|
||||
}
|
||||
});
|
||||
*/
|
||||
|
||||
// Get the remote package.json (or sub in a placeholder for new pacakges)
|
||||
let npmInfo = await getPackageVersion(info.name);
|
||||
@ -85,8 +76,10 @@ if (process.argv.length > 2) {
|
||||
progress(1);
|
||||
|
||||
try {
|
||||
log("<bold:Building TypeScript source...>");
|
||||
await runBuild();
|
||||
log("<bold:Building TypeScript source (es6)...>");
|
||||
await runBuild(true);
|
||||
log("<bold:Building TypeScript source (commonjs)...>");
|
||||
await runBuild(false);
|
||||
log("<bold:Building distribution files...>");
|
||||
let content = await runDist();
|
||||
console.log(content);
|
||||
@ -97,7 +90,7 @@ if (process.argv.length > 2) {
|
||||
}
|
||||
|
||||
// Update the tarball hash now that _version and package.json may have changed.
|
||||
progress = getProgressBar(colorify("Updating tarballHash", "bold"));
|
||||
progress = prompt.getProgressBar(colorify("Updating tarballHash", "bold"));
|
||||
for (let i = 0; i < dirnames.length; i++) {
|
||||
progress(i / dirnames.length);
|
||||
await updatePackage(dirnames[i]);
|
||||
|
@ -7,7 +7,7 @@ const resolve = require("path").resolve;
|
||||
const AES = require("aes-js");
|
||||
const scrypt = require("scrypt-js");
|
||||
|
||||
const prompt = require("../packages/cli/prompt");
|
||||
const { prompt } = require("../packages/cli");
|
||||
const randomBytes = require("../packages/random").randomBytes;
|
||||
const computeHmac = require("../packages/sha2").computeHmac;
|
||||
|
||||
|
@ -6,7 +6,7 @@ const resolve = require("path").resolve;
|
||||
const diff = require("diff");
|
||||
const semver = require("semver");
|
||||
|
||||
const { getProgressBar, prompt } = require("../packages/cli/prompt");
|
||||
const { prompt } = require("../packages/cli");
|
||||
|
||||
const build = require("./build");
|
||||
const changelog = require("./changelog");
|
||||
@ -158,7 +158,7 @@ async function runUpdate(dirnames) {
|
||||
// @TODO: Root
|
||||
|
||||
// Update all the package.json and _version.ts
|
||||
let progress = getProgressBar(colorify("Updating versions", "bold"));
|
||||
let progress = prompt.getProgressBar(colorify("Updating versions", "bold"));
|
||||
for (let i = 0; i < dirnames.length; i++) {
|
||||
progress(i / dirnames.length);
|
||||
|
||||
@ -205,7 +205,7 @@ async function runUpdate(dirnames) {
|
||||
// @TODO:
|
||||
|
||||
// Update the tarball hash now that _version and package.json may have changed.
|
||||
progress = getProgressBar(colorify("Updating tarballHash", "bold"));
|
||||
progress = prompt.getProgressBar(colorify("Updating tarballHash", "bold"));
|
||||
for (let i = 0; i < dirnames.length; i++) {
|
||||
progress(i / dirnames.length);
|
||||
await local.updatePackage(dirnames[i]);
|
||||
|
@ -2,7 +2,16 @@
|
||||
|
||||
const packlist = require("npm-packlist");
|
||||
const tar = require("tar");
|
||||
const keccak256 = require("../packages/keccak256").keccak256;
|
||||
|
||||
const keccak256 = (function() {
|
||||
try {
|
||||
return require("../packages/keccak256").keccak256;
|
||||
} catch (error) {
|
||||
console.log("Cannot load Keccak256 (maybe not built yet? Not really a problem for most things)");
|
||||
return null;
|
||||
}
|
||||
})();
|
||||
|
||||
const { dirnames, loadPackage, ROOT } = require("./depgraph");
|
||||
const { resolve, saveJson } = require("./utils");
|
||||
|
||||
|
@ -9,7 +9,7 @@ const local = require("./local");
|
||||
|
||||
const keccak256 = require("../packages/keccak256").keccak256;
|
||||
const fetchJson = require("../packages/web").fetchJson;
|
||||
const prompt = require("../packages/cli/prompt");
|
||||
const { prompt } = require("../packages/cli");
|
||||
|
||||
const colorify = require("./log").colorify;
|
||||
const git = require("./git");
|
||||
|
@ -12,18 +12,43 @@ resiliance, security and increase the amount of required trust.
|
||||
To mitigate these issues, it is recommended you use a
|
||||
[Default Provider](get-default-provider).
|
||||
|
||||
|
||||
_subsection: EtherscanProvider
|
||||
|
||||
Tra la la...
|
||||
The **EtherscanProvider** is backed by a combination of the various
|
||||
[Etherscan APIs](https://etherscan.io/apis).
|
||||
|
||||
_property: provider.getHistory(address) => Array<History>
|
||||
|
||||
|
||||
_subsection: InfuraProvider
|
||||
|
||||
Tra la la...
|
||||
The **InfuraProvider** is backed by the popular [INFURA](https://infura.io)
|
||||
Ethereum service.
|
||||
|
||||
It supports Mainnet (homestead) and all common testnets (Ropsten, Rinkeby,
|
||||
Görli and Kovan).
|
||||
|
||||
|
||||
_subsection: NodesmithProvider
|
||||
|
||||
Tra la la...
|
||||
The **NodesmithProvider** is backed by [Nodesmith](https://nodesmith.io).
|
||||
|
||||
It supports Mainnet (homestead) and all common testnets (Ropsten, Rinkeby,
|
||||
Görli and Kovan), as well as the Ethereum-like network [Aion](https://aion.network).
|
||||
|
||||
|
||||
_subsection: AlchemyProvider
|
||||
|
||||
Tra la la...
|
||||
The **AlchemtProvider** is backed by [Alchemy](https://alchemyapi.io).
|
||||
|
||||
It supports Mainnet (homestead) and all common testnets (Ropsten, Rinkeby,
|
||||
Görli and Kovan).
|
||||
|
||||
|
||||
_subsection: CloudfrontProvider
|
||||
|
||||
The CloudfrontProvider is backed by the
|
||||
[Cloudflare Ethereum Gateway](https://developers.cloudflare.com/distributed-web/ethereum-gateway/).
|
||||
|
||||
It only supports Mainnet (homestead).
|
||||
|
@ -4,23 +4,24 @@ _section: Signers
|
||||
|
||||
Tra la la...
|
||||
|
||||
_subsection: Signer
|
||||
_subsection: Signer @<signer>
|
||||
|
||||
_property: signer.connect(provider) => Signer
|
||||
_property: signer.connect(provider) => [[signer]]
|
||||
TODO
|
||||
|
||||
_heading: Blockchain Methods
|
||||
|
||||
_property: signer.getBalance([ blockTag = "latest" ]) => Promise(BigNumber)
|
||||
_property: signer.getBalance([ blockTag = "latest" ]) => Promise<[[bignumber]]>
|
||||
TODO
|
||||
|
||||
_property: signer.getTransactionCount([ blockTag = "latest" ]) => Promise(number)
|
||||
_property: signer.getTransactionCount([ blockTag = "latest" ]) => Promise<number>
|
||||
TODO
|
||||
|
||||
|
||||
_subsection: Wallet inherits Signer
|
||||
|
||||
Wallet is...
|
||||
The Wallet class inherits [[signer]] and can sign transactions and messages
|
||||
using a private key as a standard Externally Owned Account (EOA).
|
||||
|
||||
_heading: Creating an Instance
|
||||
|
||||
|
@ -84,9 +84,9 @@ the //bitcount// least significant bits set to zero.
|
||||
_heading: Two's Compliment
|
||||
|
||||
[Two's Complicment](https://en.wikipedia.org/wiki/Two%27s_complement)
|
||||
is a method used to encode and decode fixed-width values which can be
|
||||
positive or negative, without requiring a separate sign bit. Most users
|
||||
will not need to interact with these.
|
||||
is an elegant method used to encode and decode fixed-width signed values
|
||||
while efficiently preserving mathematic operations.
|
||||
Most users will not need to interact with these.
|
||||
|
||||
_property: bignumber.fromTwos(bitwidth) => [[bignumber]]
|
||||
Returns a BigNumber with the value of //bignumber// converted from twos-compliment with //bitwidth//.
|
||||
|
1782
docs.wrm/logo.ai
Normal file
1782
docs.wrm/logo.ai
Normal file
File diff suppressed because it is too large
Load Diff
42
package.json
42
package.json
@ -2,23 +2,32 @@
|
||||
"name": "root",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"auto-build": "npm run build -- -w",
|
||||
"bootstrap": "node ./admin/cmds/update-depgraph && lerna bootstrap --hoist",
|
||||
"auto-build": "node ./admin/cmds/reset-build.js && npm run build -- -w",
|
||||
"bootstrap": "node ./admin/cmds/reset-build.js && node ./admin/cmds/update-depgraph && lerna bootstrap --hoist",
|
||||
"build": "tsc --build ./tsconfig.project.json",
|
||||
"clean": "tsc --build --clean ./tsconfig.project.json",
|
||||
"_dist": "npm run clean && npm run bootstrap && npm run build && lerna run dist",
|
||||
"test": "npm run _dist && npm run test-check",
|
||||
"test-check": "if [ \"$RUN_PHANTOMJS\" = \"1\" ]; then npm run-script test-phantomjs; else npm run-script test-node; fi",
|
||||
"test-node": "cd packages/tests && mocha --no-colors --reporter ./tests/reporter ./tests/test-*.js",
|
||||
"test-phantomjs": "cd packages/tests && npm run dist-phantomjs && phantomjs --web-security=false ../../node_modules/mocha-phantomjs-core/mocha-phantomjs-core.js ./test.html ./tests/reporter.js",
|
||||
"test-aion": "npm run dist && npm run test-aion-node",
|
||||
"test-aion-node": "cd packages/aion-tests && mocha --no-colors --reporter ../tests/tests/reporter ./tests/test-*.js",
|
||||
"update-versions": "npm run clean && npm run bootstrap && npm run build && node ./admin/cmds/update-versions",
|
||||
"publish-all": "node ./admin/cmds/publish"
|
||||
"clean": "node ./admin/cmds/reset-build.js && tsc --build --clean ./tsconfig.project.json",
|
||||
"_dist_prepare": "npm run clean && npm run bootstrap && npm run build && node ./admin/cmds/update-exports.js",
|
||||
"_dist_ethers": "rollup -c && rollup -c --configMinify && rollup -c --configModule && rollup -c --configModule --configMinify",
|
||||
"_dist_tests": "rollup -c --configTest && rollup -c --configTest --configMinify && rollup -c --configTest --configModule && rollup -c --configTest --configModule --configMinify",
|
||||
"_test_prepare": "npm run _dist_prepare && npm run _dist_tests",
|
||||
"_test_node": "cd packages/tests && mocha --no-colors --reporter ./reporter ./lib/test-*.js",
|
||||
"test_node": "npm run _test_prepare && npm run _test_node",
|
||||
"_dist_old": "npm run clean && npm run bootstrap && npm run build && lerna run dist",
|
||||
"old-test": "npm run _dist_old && npm run test-check",
|
||||
"old-test-check": "if [ \"$RUN_PHANTOMJS\" = \"1\" ]; then npm run-script test-phantomjs; else npm run-script test-node; fi",
|
||||
"old-test-node": "cd packages/tests && mocha --no-colors --reporter ./tests/reporter ./tests/test-*.js",
|
||||
"old-test-phantomjs": "cd packages/tests && npm run dist-phantomjs && phantomjs --web-security=false ../../node_modules/mocha-phantomjs-core/mocha-phantomjs-core.js ./test.html ./tests/reporter.js",
|
||||
"old-test-aion": "npm run dist && npm run test-aion-node",
|
||||
"old-test-aion-node": "cd packages/aion-tests && mocha --no-colors --reporter ../tests/tests/reporter ./tests/test-*.js",
|
||||
"update-versions": "npm run _dist_prepare && node ./admin/cmds/update-versions",
|
||||
"publish-all": "node ./admin/cmds/publish",
|
||||
"lock-versions": "node ./admin/cmds/lock-versions",
|
||||
"build-docs": "flatworm docs.wrm docs"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/assert": "^1.4.1",
|
||||
"@types/mocha": "^5.2.0",
|
||||
"@types/node": "^12.7.4",
|
||||
"aes-js": "3.0.0",
|
||||
"browserify": "16.2.3",
|
||||
"diff": "4.0.1",
|
||||
@ -30,6 +39,13 @@
|
||||
"scrypt-js": "2.0.4",
|
||||
"semver": "^5.6.0",
|
||||
"tar": "4.4.8",
|
||||
"typescript": "3.3.3"
|
||||
"typescript": "3.6.2",
|
||||
"rollup": "1.20.1",
|
||||
"rollup-plugin-commonjs": "10.0.2",
|
||||
"rollup-plugin-json": "4.0.0",
|
||||
"rollup-plugin-node-resolve": "5.2.0",
|
||||
"rollup-plugin-terser": "5.1.1",
|
||||
"rollup-plugin-uglify": "6.0.2",
|
||||
"rollup-pluginutils": "2.8.1"
|
||||
}
|
||||
}
|
||||
|
1
packages/abi/lib.esm/_version.js
Normal file
1
packages/abi/lib.esm/_version.js
Normal file
@ -0,0 +1 @@
|
||||
export const version = "abi/5.0.0-beta.136";
|
91
packages/abi/lib.esm/abi-coder.js
Normal file
91
packages/abi/lib.esm/abi-coder.js
Normal file
@ -0,0 +1,91 @@
|
||||
"use strict";
|
||||
// See: https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI
|
||||
import { arrayify } from "@ethersproject/bytes";
|
||||
import { defineReadOnly } from "@ethersproject/properties";
|
||||
import { Logger } from "@ethersproject/logger";
|
||||
import { version } from "./_version";
|
||||
const logger = new Logger(version);
|
||||
import { Reader, Writer } from "./coders/abstract-coder";
|
||||
import { AddressCoder } from "./coders/address";
|
||||
import { ArrayCoder } from "./coders/array";
|
||||
import { BooleanCoder } from "./coders/boolean";
|
||||
import { BytesCoder } from "./coders/bytes";
|
||||
import { FixedBytesCoder } from "./coders/fixed-bytes";
|
||||
import { NullCoder } from "./coders/null";
|
||||
import { NumberCoder } from "./coders/number";
|
||||
import { StringCoder } from "./coders/string";
|
||||
import { TupleCoder } from "./coders/tuple";
|
||||
import { ParamType } from "./fragments";
|
||||
const paramTypeBytes = new RegExp(/^bytes([0-9]*)$/);
|
||||
const paramTypeNumber = new RegExp(/^(u?int)([0-9]*)$/);
|
||||
export class AbiCoder {
|
||||
constructor(coerceFunc) {
|
||||
logger.checkNew(new.target, AbiCoder);
|
||||
defineReadOnly(this, "coerceFunc", coerceFunc || null);
|
||||
}
|
||||
_getCoder(param) {
|
||||
switch (param.baseType) {
|
||||
case "address":
|
||||
return new AddressCoder(param.name);
|
||||
case "bool":
|
||||
return new BooleanCoder(param.name);
|
||||
case "string":
|
||||
return new StringCoder(param.name);
|
||||
case "bytes":
|
||||
return new BytesCoder(param.name);
|
||||
case "array":
|
||||
return new ArrayCoder(this._getCoder(param.arrayChildren), param.arrayLength, param.name);
|
||||
case "tuple":
|
||||
return new TupleCoder((param.components || []).map((component) => {
|
||||
return this._getCoder(component);
|
||||
}), param.name);
|
||||
case "":
|
||||
return new NullCoder(param.name);
|
||||
}
|
||||
// u?int[0-9]*
|
||||
let match = param.type.match(paramTypeNumber);
|
||||
if (match) {
|
||||
let size = parseInt(match[2] || "256");
|
||||
if (size === 0 || size > 256 || (size % 8) !== 0) {
|
||||
logger.throwArgumentError("invalid " + match[1] + " bit length", "param", param);
|
||||
}
|
||||
return new NumberCoder(size / 8, (match[1] === "int"), param.name);
|
||||
}
|
||||
// bytes[0-9]+
|
||||
match = param.type.match(paramTypeBytes);
|
||||
if (match) {
|
||||
let size = parseInt(match[1]);
|
||||
if (size === 0 || size > 32) {
|
||||
logger.throwArgumentError("invalid bytes length", "param", param);
|
||||
}
|
||||
return new FixedBytesCoder(size, param.name);
|
||||
}
|
||||
return logger.throwError("invalid type", "type", param.type);
|
||||
}
|
||||
_getWordSize() { return 32; }
|
||||
_getReader(data) {
|
||||
return new Reader(data, this._getWordSize(), this.coerceFunc);
|
||||
}
|
||||
_getWriter() {
|
||||
return new Writer(this._getWordSize());
|
||||
}
|
||||
encode(types, values) {
|
||||
if (types.length !== values.length) {
|
||||
logger.throwError("types/values length mismatch", Logger.errors.INVALID_ARGUMENT, {
|
||||
count: { types: types.length, values: values.length },
|
||||
value: { types: types, values: values }
|
||||
});
|
||||
}
|
||||
let coders = types.map((type) => this._getCoder(ParamType.from(type)));
|
||||
let coder = (new TupleCoder(coders, "_"));
|
||||
let writer = this._getWriter();
|
||||
coder.encode(writer, values);
|
||||
return writer.data;
|
||||
}
|
||||
decode(types, data) {
|
||||
let coders = types.map((type) => this._getCoder(ParamType.from(type)));
|
||||
let coder = new TupleCoder(coders, "_");
|
||||
return coder.decode(this._getReader(arrayify(data)));
|
||||
}
|
||||
}
|
||||
export const defaultAbiCoder = new AbiCoder();
|
41
packages/abi/lib.esm/coders/abstract-coder.d.ts
vendored
Normal file
41
packages/abi/lib.esm/coders/abstract-coder.d.ts
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
import { BytesLike } from "@ethersproject/bytes";
|
||||
import { BigNumber, BigNumberish } from "@ethersproject/bignumber";
|
||||
export declare type CoerceFunc = (type: string, value: any) => any;
|
||||
export declare abstract class Coder {
|
||||
readonly name: string;
|
||||
readonly type: string;
|
||||
readonly localName: string;
|
||||
readonly dynamic: boolean;
|
||||
constructor(name: string, type: string, localName: string, dynamic: boolean);
|
||||
_throwError(message: string, value: any): void;
|
||||
abstract encode(writer: Writer, value: any): number;
|
||||
abstract decode(reader: Reader): any;
|
||||
}
|
||||
export declare class Writer {
|
||||
readonly wordSize: number;
|
||||
_data: Uint8Array;
|
||||
_padding: Uint8Array;
|
||||
constructor(wordSize?: number);
|
||||
readonly data: string;
|
||||
readonly length: number;
|
||||
_writeData(data: Uint8Array): number;
|
||||
writeBytes(value: BytesLike): number;
|
||||
_getValue(value: BigNumberish): Uint8Array;
|
||||
writeValue(value: BigNumberish): number;
|
||||
writeUpdatableValue(): (value: BigNumberish) => void;
|
||||
}
|
||||
export declare class Reader {
|
||||
readonly wordSize: number;
|
||||
readonly _data: Uint8Array;
|
||||
readonly _coerceFunc: CoerceFunc;
|
||||
_offset: number;
|
||||
constructor(data: BytesLike, wordSize?: number, coerceFunc?: CoerceFunc);
|
||||
readonly data: string;
|
||||
readonly consumed: number;
|
||||
static coerce(name: string, value: any): any;
|
||||
coerce(name: string, value: any): any;
|
||||
_peekBytes(offset: number, length: number): Uint8Array;
|
||||
subReader(offset: number): Reader;
|
||||
readBytes(length: number): Uint8Array;
|
||||
readValue(): BigNumber;
|
||||
}
|
109
packages/abi/lib.esm/coders/abstract-coder.js
Normal file
109
packages/abi/lib.esm/coders/abstract-coder.js
Normal file
@ -0,0 +1,109 @@
|
||||
"use strict";
|
||||
import { arrayify, concat, hexlify } from "@ethersproject/bytes";
|
||||
import { BigNumber } from "@ethersproject/bignumber";
|
||||
import { defineReadOnly } from "@ethersproject/properties";
|
||||
import { Logger } from "@ethersproject/logger";
|
||||
import { version } from "../_version";
|
||||
const logger = new Logger(version);
|
||||
export class Coder {
|
||||
constructor(name, type, localName, dynamic) {
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
this.localName = localName;
|
||||
this.dynamic = dynamic;
|
||||
}
|
||||
_throwError(message, value) {
|
||||
logger.throwArgumentError(message, this.localName, value);
|
||||
}
|
||||
}
|
||||
export class Writer {
|
||||
constructor(wordSize) {
|
||||
defineReadOnly(this, "wordSize", wordSize || 32);
|
||||
this._data = arrayify([]);
|
||||
this._padding = new Uint8Array(wordSize);
|
||||
}
|
||||
get data() { return hexlify(this._data); }
|
||||
get length() { return this._data.length; }
|
||||
_writeData(data) {
|
||||
this._data = concat([this._data, data]);
|
||||
return data.length;
|
||||
}
|
||||
// Arrayish items; padded on the right to wordSize
|
||||
writeBytes(value) {
|
||||
let bytes = arrayify(value);
|
||||
if (bytes.length % this.wordSize) {
|
||||
bytes = concat([bytes, this._padding.slice(bytes.length % this.wordSize)]);
|
||||
}
|
||||
return this._writeData(bytes);
|
||||
}
|
||||
_getValue(value) {
|
||||
let bytes = arrayify(BigNumber.from(value));
|
||||
if (bytes.length > this.wordSize) {
|
||||
logger.throwError("value out-of-bounds", Logger.errors.BUFFER_OVERRUN, {
|
||||
length: this.wordSize,
|
||||
offset: bytes.length
|
||||
});
|
||||
}
|
||||
if (bytes.length % this.wordSize) {
|
||||
bytes = concat([this._padding.slice(bytes.length % this.wordSize), bytes]);
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
// BigNumberish items; padded on the left to wordSize
|
||||
writeValue(value) {
|
||||
return this._writeData(this._getValue(value));
|
||||
}
|
||||
writeUpdatableValue() {
|
||||
let offset = this.length;
|
||||
this.writeValue(0);
|
||||
return (value) => {
|
||||
this._data.set(this._getValue(value), offset);
|
||||
};
|
||||
}
|
||||
}
|
||||
export class Reader {
|
||||
constructor(data, wordSize, coerceFunc) {
|
||||
defineReadOnly(this, "_data", arrayify(data));
|
||||
defineReadOnly(this, "wordSize", wordSize || 32);
|
||||
defineReadOnly(this, "_coerceFunc", coerceFunc);
|
||||
this._offset = 0;
|
||||
}
|
||||
get data() { return hexlify(this._data); }
|
||||
get consumed() { return this._offset; }
|
||||
// The default Coerce function
|
||||
static coerce(name, value) {
|
||||
let match = name.match("^u?int([0-9]+)$");
|
||||
if (match && parseInt(match[1]) <= 48) {
|
||||
value = value.toNumber();
|
||||
}
|
||||
return value;
|
||||
}
|
||||
coerce(name, value) {
|
||||
if (this._coerceFunc) {
|
||||
return this._coerceFunc(name, value);
|
||||
}
|
||||
return Reader.coerce(name, value);
|
||||
}
|
||||
_peekBytes(offset, length) {
|
||||
let alignedLength = Math.ceil(length / this.wordSize) * this.wordSize;
|
||||
if (this._offset + alignedLength > this._data.length) {
|
||||
logger.throwError("data out-of-bounds", Logger.errors.BUFFER_OVERRUN, {
|
||||
length: this._data.length,
|
||||
offset: this._offset + alignedLength
|
||||
});
|
||||
}
|
||||
return this._data.slice(this._offset, this._offset + alignedLength);
|
||||
}
|
||||
subReader(offset) {
|
||||
return new Reader(this._data.slice(this._offset + offset), this.wordSize, this._coerceFunc);
|
||||
}
|
||||
readBytes(length) {
|
||||
let bytes = this._peekBytes(0, length);
|
||||
this._offset += bytes.length;
|
||||
// @TODO: Make sure the length..end bytes are all 0?
|
||||
return bytes.slice(0, length);
|
||||
}
|
||||
readValue() {
|
||||
return BigNumber.from(this.readBytes(this.wordSize));
|
||||
}
|
||||
}
|
6
packages/abi/lib.esm/coders/address.d.ts
vendored
Normal file
6
packages/abi/lib.esm/coders/address.d.ts
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
import { Coder, Reader, Writer } from "./abstract-coder";
|
||||
export declare class AddressCoder extends Coder {
|
||||
constructor(localName: string);
|
||||
encode(writer: Writer, value: string): number;
|
||||
decode(reader: Reader): any;
|
||||
}
|
21
packages/abi/lib.esm/coders/address.js
Normal file
21
packages/abi/lib.esm/coders/address.js
Normal file
@ -0,0 +1,21 @@
|
||||
"use strict";
|
||||
import { getAddress } from "@ethersproject/address";
|
||||
import { hexZeroPad } from "@ethersproject/bytes";
|
||||
import { Coder } from "./abstract-coder";
|
||||
export class AddressCoder extends Coder {
|
||||
constructor(localName) {
|
||||
super("address", "address", localName, false);
|
||||
}
|
||||
encode(writer, value) {
|
||||
try {
|
||||
getAddress(value);
|
||||
}
|
||||
catch (error) {
|
||||
this._throwError(error.message, value);
|
||||
}
|
||||
return writer.writeValue(value);
|
||||
}
|
||||
decode(reader) {
|
||||
return getAddress(hexZeroPad(reader.readValue().toHexString(), 20));
|
||||
}
|
||||
}
|
7
packages/abi/lib.esm/coders/anonymous.d.ts
vendored
Normal file
7
packages/abi/lib.esm/coders/anonymous.d.ts
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
import { Coder, Reader, Writer } from "./abstract-coder";
|
||||
export declare class AnonymousCoder extends Coder {
|
||||
private coder;
|
||||
constructor(coder: Coder);
|
||||
encode(writer: Writer, value: any): number;
|
||||
decode(reader: Reader): any;
|
||||
}
|
15
packages/abi/lib.esm/coders/anonymous.js
Normal file
15
packages/abi/lib.esm/coders/anonymous.js
Normal file
@ -0,0 +1,15 @@
|
||||
"use strict";
|
||||
import { Coder } from "./abstract-coder";
|
||||
// Clones the functionality of an existing Coder, but without a localName
|
||||
export class AnonymousCoder extends Coder {
|
||||
constructor(coder) {
|
||||
super(coder.name, coder.type, undefined, coder.dynamic);
|
||||
this.coder = coder;
|
||||
}
|
||||
encode(writer, value) {
|
||||
return this.coder.encode(writer, value);
|
||||
}
|
||||
decode(reader) {
|
||||
return this.coder.decode(reader);
|
||||
}
|
||||
}
|
10
packages/abi/lib.esm/coders/array.d.ts
vendored
Normal file
10
packages/abi/lib.esm/coders/array.d.ts
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
import { Coder, Reader, Writer } from "./abstract-coder";
|
||||
export declare function pack(writer: Writer, coders: Array<Coder>, values: Array<any>): number;
|
||||
export declare function unpack(reader: Reader, coders: Array<Coder>): Array<any>;
|
||||
export declare class ArrayCoder extends Coder {
|
||||
readonly coder: Coder;
|
||||
readonly length: number;
|
||||
constructor(coder: Coder, length: number, localName: string);
|
||||
encode(writer: Writer, value: Array<any>): number;
|
||||
decode(reader: Reader): any;
|
||||
}
|
126
packages/abi/lib.esm/coders/array.js
Normal file
126
packages/abi/lib.esm/coders/array.js
Normal file
@ -0,0 +1,126 @@
|
||||
"use strict";
|
||||
import { Logger } from "@ethersproject/logger";
|
||||
import { version } from "../_version";
|
||||
const logger = new Logger(version);
|
||||
import { Coder, Writer } from "./abstract-coder";
|
||||
import { AnonymousCoder } from "./anonymous";
|
||||
export function pack(writer, coders, values) {
|
||||
if (Array.isArray(values)) {
|
||||
// do nothing
|
||||
}
|
||||
else if (values && typeof (values) === "object") {
|
||||
let arrayValues = [];
|
||||
coders.forEach(function (coder) {
|
||||
arrayValues.push(values[coder.localName]);
|
||||
});
|
||||
values = arrayValues;
|
||||
}
|
||||
else {
|
||||
logger.throwArgumentError("invalid tuple value", "tuple", values);
|
||||
}
|
||||
if (coders.length !== values.length) {
|
||||
logger.throwArgumentError("types/value length mismatch", "tuple", values);
|
||||
}
|
||||
let staticWriter = new Writer(writer.wordSize);
|
||||
let dynamicWriter = new Writer(writer.wordSize);
|
||||
let updateFuncs = [];
|
||||
coders.forEach((coder, index) => {
|
||||
let value = values[index];
|
||||
if (coder.dynamic) {
|
||||
// Get current dynamic offset (for the future pointer)
|
||||
let dynamicOffset = dynamicWriter.length;
|
||||
// Encode the dynamic value into the dynamicWriter
|
||||
coder.encode(dynamicWriter, value);
|
||||
// Prepare to populate the correct offset once we are done
|
||||
let updateFunc = staticWriter.writeUpdatableValue();
|
||||
updateFuncs.push((baseOffset) => {
|
||||
updateFunc(baseOffset + dynamicOffset);
|
||||
});
|
||||
}
|
||||
else {
|
||||
coder.encode(staticWriter, value);
|
||||
}
|
||||
});
|
||||
// Backfill all the dynamic offsets, now that we know the static length
|
||||
updateFuncs.forEach((func) => { func(staticWriter.length); });
|
||||
let length = writer.writeBytes(staticWriter.data);
|
||||
length += writer.writeBytes(dynamicWriter.data);
|
||||
return length;
|
||||
}
|
||||
export function unpack(reader, coders) {
|
||||
let values = [];
|
||||
// A reader anchored to this base
|
||||
let baseReader = reader.subReader(0);
|
||||
// The amount of dynamic data read; to consume later to synchronize
|
||||
let dynamicLength = 0;
|
||||
coders.forEach((coder) => {
|
||||
let value = null;
|
||||
if (coder.dynamic) {
|
||||
let offset = reader.readValue();
|
||||
let offsetReader = baseReader.subReader(offset.toNumber());
|
||||
value = coder.decode(offsetReader);
|
||||
dynamicLength += offsetReader.consumed;
|
||||
}
|
||||
else {
|
||||
value = coder.decode(reader);
|
||||
}
|
||||
if (value != undefined) {
|
||||
values.push(value);
|
||||
}
|
||||
});
|
||||
// @TODO: get rid of this an see if it still works?
|
||||
// Consume the dynamic components in the main reader
|
||||
reader.readBytes(dynamicLength);
|
||||
// Add any named parameters (i.e. tuples)
|
||||
coders.forEach((coder, index) => {
|
||||
let name = coder.localName;
|
||||
if (!name) {
|
||||
return;
|
||||
}
|
||||
if (name === "length") {
|
||||
name = "_length";
|
||||
}
|
||||
if (values[name] != null) {
|
||||
return;
|
||||
}
|
||||
values[name] = values[index];
|
||||
});
|
||||
return values;
|
||||
}
|
||||
export class ArrayCoder extends Coder {
|
||||
constructor(coder, length, localName) {
|
||||
const type = (coder.type + "[" + (length >= 0 ? length : "") + "]");
|
||||
const dynamic = (length === -1 || coder.dynamic);
|
||||
super("array", type, localName, dynamic);
|
||||
this.coder = coder;
|
||||
this.length = length;
|
||||
}
|
||||
encode(writer, value) {
|
||||
if (!Array.isArray(value)) {
|
||||
this._throwError("expected array value", value);
|
||||
}
|
||||
let count = this.length;
|
||||
//let result = new Uint8Array(0);
|
||||
if (count === -1) {
|
||||
count = value.length;
|
||||
writer.writeValue(value.length);
|
||||
}
|
||||
logger.checkArgumentCount(count, value.length, "coder array" + (this.localName ? (" " + this.localName) : ""));
|
||||
let coders = [];
|
||||
for (let i = 0; i < value.length; i++) {
|
||||
coders.push(this.coder);
|
||||
}
|
||||
return pack(writer, coders, value);
|
||||
}
|
||||
decode(reader) {
|
||||
let count = this.length;
|
||||
if (count === -1) {
|
||||
count = reader.readValue().toNumber();
|
||||
}
|
||||
let coders = [];
|
||||
for (let i = 0; i < count; i++) {
|
||||
coders.push(new AnonymousCoder(this.coder));
|
||||
}
|
||||
return reader.coerce(this.name, unpack(reader, coders));
|
||||
}
|
||||
}
|
6
packages/abi/lib.esm/coders/boolean.d.ts
vendored
Normal file
6
packages/abi/lib.esm/coders/boolean.d.ts
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
import { Coder, Reader, Writer } from "./abstract-coder";
|
||||
export declare class BooleanCoder extends Coder {
|
||||
constructor(localName: string);
|
||||
encode(writer: Writer, value: boolean): number;
|
||||
decode(reader: Reader): any;
|
||||
}
|
13
packages/abi/lib.esm/coders/boolean.js
Normal file
13
packages/abi/lib.esm/coders/boolean.js
Normal file
@ -0,0 +1,13 @@
|
||||
"use strict";
|
||||
import { Coder } from "./abstract-coder";
|
||||
export class BooleanCoder extends Coder {
|
||||
constructor(localName) {
|
||||
super("bool", "bool", localName, false);
|
||||
}
|
||||
encode(writer, value) {
|
||||
return writer.writeValue(value ? 1 : 0);
|
||||
}
|
||||
decode(reader) {
|
||||
return reader.coerce(this.type, !reader.readValue().isZero());
|
||||
}
|
||||
}
|
10
packages/abi/lib.esm/coders/bytes.d.ts
vendored
Normal file
10
packages/abi/lib.esm/coders/bytes.d.ts
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
import { Coder, Reader, Writer } from "./abstract-coder";
|
||||
export declare class DynamicBytesCoder extends Coder {
|
||||
constructor(type: string, localName: string);
|
||||
encode(writer: Writer, value: any): number;
|
||||
decode(reader: Reader): any;
|
||||
}
|
||||
export declare class BytesCoder extends DynamicBytesCoder {
|
||||
constructor(localName: string);
|
||||
decode(reader: Reader): any;
|
||||
}
|
25
packages/abi/lib.esm/coders/bytes.js
Normal file
25
packages/abi/lib.esm/coders/bytes.js
Normal file
@ -0,0 +1,25 @@
|
||||
"use strict";
|
||||
import { arrayify, hexlify } from "@ethersproject/bytes";
|
||||
import { Coder } from "./abstract-coder";
|
||||
export class DynamicBytesCoder extends Coder {
|
||||
constructor(type, localName) {
|
||||
super(type, type, localName, true);
|
||||
}
|
||||
encode(writer, value) {
|
||||
value = arrayify(value);
|
||||
let length = writer.writeValue(value.length);
|
||||
length += writer.writeBytes(value);
|
||||
return length;
|
||||
}
|
||||
decode(reader) {
|
||||
return reader.readBytes(reader.readValue().toNumber());
|
||||
}
|
||||
}
|
||||
export class BytesCoder extends DynamicBytesCoder {
|
||||
constructor(localName) {
|
||||
super("bytes", localName);
|
||||
}
|
||||
decode(reader) {
|
||||
return reader.coerce(this.name, hexlify(super.decode(reader)));
|
||||
}
|
||||
}
|
8
packages/abi/lib.esm/coders/fixed-bytes.d.ts
vendored
Normal file
8
packages/abi/lib.esm/coders/fixed-bytes.d.ts
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
import { BytesLike } from "@ethersproject/bytes";
|
||||
import { Coder, Reader, Writer } from "./abstract-coder";
|
||||
export declare class FixedBytesCoder extends Coder {
|
||||
readonly size: number;
|
||||
constructor(size: number, localName: string);
|
||||
encode(writer: Writer, value: BytesLike): number;
|
||||
decode(reader: Reader): any;
|
||||
}
|
21
packages/abi/lib.esm/coders/fixed-bytes.js
Normal file
21
packages/abi/lib.esm/coders/fixed-bytes.js
Normal file
@ -0,0 +1,21 @@
|
||||
"use strict";
|
||||
import { arrayify, hexlify } from "@ethersproject/bytes";
|
||||
import { Coder } from "./abstract-coder";
|
||||
// @TODO: Merge this with bytes
|
||||
export class FixedBytesCoder extends Coder {
|
||||
constructor(size, localName) {
|
||||
let name = "bytes" + String(size);
|
||||
super(name, name, localName, false);
|
||||
this.size = size;
|
||||
}
|
||||
encode(writer, value) {
|
||||
let data = arrayify(value);
|
||||
if (data.length !== this.size) {
|
||||
this._throwError("incorrect data length", value);
|
||||
}
|
||||
return writer.writeBytes(data);
|
||||
}
|
||||
decode(reader) {
|
||||
return reader.coerce(this.name, hexlify(reader.readBytes(this.size)));
|
||||
}
|
||||
}
|
6
packages/abi/lib.esm/coders/null.d.ts
vendored
Normal file
6
packages/abi/lib.esm/coders/null.d.ts
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
import { Coder, Reader, Writer } from "./abstract-coder";
|
||||
export declare class NullCoder extends Coder {
|
||||
constructor(localName: string);
|
||||
encode(writer: Writer, value: any): number;
|
||||
decode(reader: Reader): any;
|
||||
}
|
17
packages/abi/lib.esm/coders/null.js
Normal file
17
packages/abi/lib.esm/coders/null.js
Normal file
@ -0,0 +1,17 @@
|
||||
"use strict";
|
||||
import { Coder } from "./abstract-coder";
|
||||
export class NullCoder extends Coder {
|
||||
constructor(localName) {
|
||||
super("null", "", localName, false);
|
||||
}
|
||||
encode(writer, value) {
|
||||
if (value != null) {
|
||||
this._throwError("not null", value);
|
||||
}
|
||||
return writer.writeBytes([]);
|
||||
}
|
||||
decode(reader) {
|
||||
reader.readBytes(0);
|
||||
return reader.coerce(this.name, null);
|
||||
}
|
||||
}
|
9
packages/abi/lib.esm/coders/number.d.ts
vendored
Normal file
9
packages/abi/lib.esm/coders/number.d.ts
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
import { BigNumberish } from "@ethersproject/bignumber";
|
||||
import { Coder, Reader, Writer } from "./abstract-coder";
|
||||
export declare class NumberCoder extends Coder {
|
||||
readonly size: number;
|
||||
readonly signed: boolean;
|
||||
constructor(size: number, signed: boolean, localName: string);
|
||||
encode(writer: Writer, value: BigNumberish): number;
|
||||
decode(reader: Reader): any;
|
||||
}
|
38
packages/abi/lib.esm/coders/number.js
Normal file
38
packages/abi/lib.esm/coders/number.js
Normal file
@ -0,0 +1,38 @@
|
||||
"use strict";
|
||||
import { BigNumber } from "@ethersproject/bignumber";
|
||||
import { MaxUint256, NegativeOne, One, Zero } from "@ethersproject/constants";
|
||||
import { Coder } from "./abstract-coder";
|
||||
export class NumberCoder extends Coder {
|
||||
constructor(size, signed, localName) {
|
||||
const name = ((signed ? "int" : "uint") + (size * 8));
|
||||
super(name, name, localName, false);
|
||||
this.size = size;
|
||||
this.signed = signed;
|
||||
}
|
||||
encode(writer, value) {
|
||||
let v = BigNumber.from(value);
|
||||
// Check bounds are safe for encoding
|
||||
let maxUintValue = MaxUint256.maskn(writer.wordSize * 8);
|
||||
if (this.signed) {
|
||||
let bounds = maxUintValue.maskn(this.size * 8 - 1);
|
||||
if (v.gt(bounds) || v.lt(bounds.add(One).mul(NegativeOne))) {
|
||||
this._throwError("value out-of-bounds", value);
|
||||
}
|
||||
}
|
||||
else if (v.lt(Zero) || v.gt(maxUintValue.maskn(this.size * 8))) {
|
||||
this._throwError("value out-of-bounds", value);
|
||||
}
|
||||
v = v.toTwos(this.size * 8).maskn(this.size * 8);
|
||||
if (this.signed) {
|
||||
v = v.fromTwos(this.size * 8).toTwos(8 * writer.wordSize);
|
||||
}
|
||||
return writer.writeValue(v);
|
||||
}
|
||||
decode(reader) {
|
||||
let value = reader.readValue().maskn(this.size * 8);
|
||||
if (this.signed) {
|
||||
value = value.fromTwos(this.size * 8);
|
||||
}
|
||||
return reader.coerce(this.name, value);
|
||||
}
|
||||
}
|
7
packages/abi/lib.esm/coders/string.d.ts
vendored
Normal file
7
packages/abi/lib.esm/coders/string.d.ts
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
import { Reader, Writer } from "./abstract-coder";
|
||||
import { DynamicBytesCoder } from "./bytes";
|
||||
export declare class StringCoder extends DynamicBytesCoder {
|
||||
constructor(localName: string);
|
||||
encode(writer: Writer, value: any): number;
|
||||
decode(reader: Reader): any;
|
||||
}
|
14
packages/abi/lib.esm/coders/string.js
Normal file
14
packages/abi/lib.esm/coders/string.js
Normal file
@ -0,0 +1,14 @@
|
||||
"use strict";
|
||||
import { toUtf8Bytes, toUtf8String } from "@ethersproject/strings";
|
||||
import { DynamicBytesCoder } from "./bytes";
|
||||
export class StringCoder extends DynamicBytesCoder {
|
||||
constructor(localName) {
|
||||
super("string", localName);
|
||||
}
|
||||
encode(writer, value) {
|
||||
return super.encode(writer, toUtf8Bytes(value));
|
||||
}
|
||||
decode(reader) {
|
||||
return toUtf8String(super.decode(reader));
|
||||
}
|
||||
}
|
7
packages/abi/lib.esm/coders/tuple.d.ts
vendored
Normal file
7
packages/abi/lib.esm/coders/tuple.d.ts
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
import { Coder, Reader, Writer } from "./abstract-coder";
|
||||
export declare class TupleCoder extends Coder {
|
||||
readonly coders: Array<Coder>;
|
||||
constructor(coders: Array<Coder>, localName: string);
|
||||
encode(writer: Writer, value: Array<any>): number;
|
||||
decode(reader: Reader): any;
|
||||
}
|
24
packages/abi/lib.esm/coders/tuple.js
Normal file
24
packages/abi/lib.esm/coders/tuple.js
Normal file
@ -0,0 +1,24 @@
|
||||
"use strict";
|
||||
import { Coder } from "./abstract-coder";
|
||||
import { pack, unpack } from "./array";
|
||||
export class TupleCoder extends Coder {
|
||||
constructor(coders, localName) {
|
||||
let dynamic = false;
|
||||
let types = [];
|
||||
coders.forEach((coder) => {
|
||||
if (coder.dynamic) {
|
||||
dynamic = true;
|
||||
}
|
||||
types.push(coder.type);
|
||||
});
|
||||
let type = ("tuple(" + types.join(",") + ")");
|
||||
super("tuple", type, localName, dynamic);
|
||||
this.coders = coders;
|
||||
}
|
||||
encode(writer, value) {
|
||||
return pack(writer, this.coders, value);
|
||||
}
|
||||
decode(reader) {
|
||||
return reader.coerce(this.name, unpack(reader, this.coders));
|
||||
}
|
||||
}
|
752
packages/abi/lib.esm/fragments.js
Normal file
752
packages/abi/lib.esm/fragments.js
Normal file
@ -0,0 +1,752 @@
|
||||
"use strict";
|
||||
import { BigNumber } from "@ethersproject/bignumber";
|
||||
import { defineReadOnly } from "@ethersproject/properties";
|
||||
import { Logger } from "@ethersproject/logger";
|
||||
import { version } from "./_version";
|
||||
const logger = new Logger(version);
|
||||
;
|
||||
const _constructorGuard = {};
|
||||
let ModifiersBytes = { calldata: true, memory: true, storage: true };
|
||||
function checkModifier(type, name) {
|
||||
if (type === "bytes" || type === "string") {
|
||||
if (ModifiersBytes[name]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (type === "address") {
|
||||
if (name === "payable") {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (ModifiersBytes[name] || name === "payable") {
|
||||
logger.throwArgumentError("invalid modifier", "name", name);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// @TODO: Make sure that children of an indexed tuple are marked with a null indexed
|
||||
function parseParamType(param, allowIndexed) {
|
||||
let originalParam = param;
|
||||
function throwError(i) {
|
||||
throw new Error("unexpected character '" + originalParam[i] + "' at position " + i + " in '" + originalParam + "'");
|
||||
}
|
||||
param = param.replace(/\s/g, " ");
|
||||
function newNode(parent) {
|
||||
let node = { type: "", name: "", parent: parent, state: { allowType: true } };
|
||||
if (allowIndexed) {
|
||||
node.indexed = false;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
let parent = { type: "", name: "", state: { allowType: true } };
|
||||
let node = parent;
|
||||
for (let i = 0; i < param.length; i++) {
|
||||
let c = param[i];
|
||||
switch (c) {
|
||||
case "(":
|
||||
if (!node.state.allowParams) {
|
||||
throwError(i);
|
||||
}
|
||||
node.state.allowType = false;
|
||||
node.type = verifyType(node.type);
|
||||
node.components = [newNode(node)];
|
||||
node = node.components[0];
|
||||
break;
|
||||
case ")":
|
||||
delete node.state;
|
||||
if (node.name === "indexed") {
|
||||
if (!allowIndexed) {
|
||||
throwError(i);
|
||||
}
|
||||
node.indexed = true;
|
||||
node.name = "";
|
||||
}
|
||||
if (checkModifier(node.type, node.name)) {
|
||||
node.name = "";
|
||||
}
|
||||
node.type = verifyType(node.type);
|
||||
let child = node;
|
||||
node = node.parent;
|
||||
if (!node) {
|
||||
throwError(i);
|
||||
}
|
||||
delete child.parent;
|
||||
node.state.allowParams = false;
|
||||
node.state.allowName = true;
|
||||
node.state.allowArray = true;
|
||||
break;
|
||||
case ",":
|
||||
delete node.state;
|
||||
if (node.name === "indexed") {
|
||||
if (!allowIndexed) {
|
||||
throwError(i);
|
||||
}
|
||||
node.indexed = true;
|
||||
node.name = "";
|
||||
}
|
||||
if (checkModifier(node.type, node.name)) {
|
||||
node.name = "";
|
||||
}
|
||||
node.type = verifyType(node.type);
|
||||
let sibling = newNode(node.parent);
|
||||
//{ type: "", name: "", parent: node.parent, state: { allowType: true } };
|
||||
node.parent.components.push(sibling);
|
||||
delete node.parent;
|
||||
node = sibling;
|
||||
break;
|
||||
// Hit a space...
|
||||
case " ":
|
||||
// If reading type, the type is done and may read a param or name
|
||||
if (node.state.allowType) {
|
||||
if (node.type !== "") {
|
||||
node.type = verifyType(node.type);
|
||||
delete node.state.allowType;
|
||||
node.state.allowName = true;
|
||||
node.state.allowParams = true;
|
||||
}
|
||||
}
|
||||
// If reading name, the name is done
|
||||
if (node.state.allowName) {
|
||||
if (node.name !== "") {
|
||||
if (node.name === "indexed") {
|
||||
if (!allowIndexed) {
|
||||
throwError(i);
|
||||
}
|
||||
if (node.indexed) {
|
||||
throwError(i);
|
||||
}
|
||||
node.indexed = true;
|
||||
node.name = "";
|
||||
}
|
||||
else if (checkModifier(node.type, node.name)) {
|
||||
node.name = "";
|
||||
}
|
||||
else {
|
||||
node.state.allowName = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "[":
|
||||
if (!node.state.allowArray) {
|
||||
throwError(i);
|
||||
}
|
||||
node.type += c;
|
||||
node.state.allowArray = false;
|
||||
node.state.allowName = false;
|
||||
node.state.readArray = true;
|
||||
break;
|
||||
case "]":
|
||||
if (!node.state.readArray) {
|
||||
throwError(i);
|
||||
}
|
||||
node.type += c;
|
||||
node.state.readArray = false;
|
||||
node.state.allowArray = true;
|
||||
node.state.allowName = true;
|
||||
break;
|
||||
default:
|
||||
if (node.state.allowType) {
|
||||
node.type += c;
|
||||
node.state.allowParams = true;
|
||||
node.state.allowArray = true;
|
||||
}
|
||||
else if (node.state.allowName) {
|
||||
node.name += c;
|
||||
delete node.state.allowArray;
|
||||
}
|
||||
else if (node.state.readArray) {
|
||||
node.type += c;
|
||||
}
|
||||
else {
|
||||
throwError(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (node.parent) {
|
||||
throw new Error("unexpected eof");
|
||||
}
|
||||
delete parent.state;
|
||||
if (node.name === "indexed") {
|
||||
if (!allowIndexed) {
|
||||
throwError(originalParam.length - 7);
|
||||
}
|
||||
if (node.indexed) {
|
||||
throwError(originalParam.length - 7);
|
||||
}
|
||||
node.indexed = true;
|
||||
node.name = "";
|
||||
}
|
||||
else if (checkModifier(node.type, node.name)) {
|
||||
node.name = "";
|
||||
}
|
||||
parent.type = verifyType(parent.type);
|
||||
return parent;
|
||||
}
|
||||
function populate(object, params) {
|
||||
for (let key in params) {
|
||||
defineReadOnly(object, key, params[key]);
|
||||
}
|
||||
}
|
||||
export const FormatTypes = Object.freeze({
|
||||
// Bare formatting, as is needed for computing a sighash of an event or function
|
||||
sighash: "sighash",
|
||||
// Human-Readable with Minimal spacing and without names (compact human-readable)
|
||||
minimal: "minimal",
|
||||
// Human-Readble with nice spacing, including all names
|
||||
full: "full",
|
||||
// JSON-format a la Solidity
|
||||
json: "json"
|
||||
});
|
||||
const paramTypeArray = new RegExp(/^(.*)\[([0-9]*)\]$/);
|
||||
export class ParamType {
|
||||
constructor(constructorGuard, params) {
|
||||
if (constructorGuard !== _constructorGuard) {
|
||||
throw new Error("use fromString");
|
||||
}
|
||||
populate(this, params);
|
||||
let match = this.type.match(paramTypeArray);
|
||||
if (match) {
|
||||
populate(this, {
|
||||
arrayLength: parseInt(match[2] || "-1"),
|
||||
arrayChildren: ParamType.fromObject({
|
||||
type: match[1],
|
||||
components: this.components
|
||||
}),
|
||||
baseType: "array"
|
||||
});
|
||||
}
|
||||
else {
|
||||
populate(this, {
|
||||
arrayLength: null,
|
||||
arrayChildren: null,
|
||||
baseType: ((this.components != null) ? "tuple" : this.type)
|
||||
});
|
||||
}
|
||||
this._isParamType = true;
|
||||
Object.freeze(this);
|
||||
}
|
||||
// Format the parameter fragment
|
||||
// - sighash: "(uint256,address)"
|
||||
// - minimal: "tuple(uint256,address) indexed"
|
||||
// - full: "tuple(uint256 foo, addres bar) indexed baz"
|
||||
format(format) {
|
||||
if (!format) {
|
||||
format = FormatTypes.sighash;
|
||||
}
|
||||
if (!FormatTypes[format]) {
|
||||
logger.throwArgumentError("invalid format type", "format", format);
|
||||
}
|
||||
if (format === FormatTypes.json) {
|
||||
let result = {
|
||||
type: ((this.baseType === "tuple") ? "tuple" : this.type),
|
||||
name: (this.name || undefined)
|
||||
};
|
||||
if (typeof (this.indexed) === "boolean") {
|
||||
result.indexed = this.indexed;
|
||||
}
|
||||
if (this.components) {
|
||||
result.components = this.components.map((comp) => JSON.parse(comp.format(format)));
|
||||
}
|
||||
return JSON.stringify(result);
|
||||
}
|
||||
let result = "";
|
||||
// Array
|
||||
if (this.baseType === "array") {
|
||||
result += this.arrayChildren.format(format);
|
||||
result += "[" + (this.arrayLength < 0 ? "" : String(this.arrayLength)) + "]";
|
||||
}
|
||||
else {
|
||||
if (this.baseType === "tuple") {
|
||||
if (format !== FormatTypes.sighash) {
|
||||
result += this.type;
|
||||
}
|
||||
result += "(" + this.components.map((comp) => comp.format(format)).join((format === FormatTypes.full) ? ", " : ",") + ")";
|
||||
}
|
||||
else {
|
||||
result += this.type;
|
||||
}
|
||||
}
|
||||
if (format !== FormatTypes.sighash) {
|
||||
if (this.indexed === true) {
|
||||
result += " indexed";
|
||||
}
|
||||
if (format === FormatTypes.full && this.name) {
|
||||
result += " " + this.name;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
static from(value, allowIndexed) {
|
||||
if (typeof (value) === "string") {
|
||||
return ParamType.fromString(value, allowIndexed);
|
||||
}
|
||||
return ParamType.fromObject(value);
|
||||
}
|
||||
static fromObject(value) {
|
||||
if (ParamType.isParamType(value)) {
|
||||
return value;
|
||||
}
|
||||
return new ParamType(_constructorGuard, {
|
||||
name: (value.name || null),
|
||||
type: verifyType(value.type),
|
||||
indexed: ((value.indexed == null) ? null : !!value.indexed),
|
||||
components: (value.components ? value.components.map(ParamType.fromObject) : null)
|
||||
});
|
||||
}
|
||||
static fromString(value, allowIndexed) {
|
||||
function ParamTypify(node) {
|
||||
return ParamType.fromObject({
|
||||
name: node.name,
|
||||
type: node.type,
|
||||
indexed: node.indexed,
|
||||
components: node.components
|
||||
});
|
||||
}
|
||||
return ParamTypify(parseParamType(value, !!allowIndexed));
|
||||
}
|
||||
static isParamType(value) {
|
||||
return !!(value != null && value._isParamType);
|
||||
}
|
||||
}
|
||||
;
|
||||
function parseParams(value, allowIndex) {
|
||||
return splitNesting(value).map((param) => ParamType.fromString(param, allowIndex));
|
||||
}
|
||||
export class Fragment {
|
||||
constructor(constructorGuard, params) {
|
||||
if (constructorGuard !== _constructorGuard) {
|
||||
throw new Error("use a static from method");
|
||||
}
|
||||
populate(this, params);
|
||||
this._isFragment = true;
|
||||
Object.freeze(this);
|
||||
}
|
||||
static from(value) {
|
||||
if (Fragment.isFragment(value)) {
|
||||
return value;
|
||||
}
|
||||
if (typeof (value) === "string") {
|
||||
return Fragment.fromString(value);
|
||||
}
|
||||
return Fragment.fromObject(value);
|
||||
}
|
||||
static fromObject(value) {
|
||||
if (Fragment.isFragment(value)) {
|
||||
return value;
|
||||
}
|
||||
if (value.type === "function") {
|
||||
return FunctionFragment.fromObject(value);
|
||||
}
|
||||
else if (value.type === "event") {
|
||||
return EventFragment.fromObject(value);
|
||||
}
|
||||
else if (value.type === "constructor") {
|
||||
return ConstructorFragment.fromObject(value);
|
||||
}
|
||||
else if (value.type === "fallback") {
|
||||
// @TODO:
|
||||
return null;
|
||||
}
|
||||
return logger.throwArgumentError("invalid fragment object", "value", value);
|
||||
}
|
||||
static fromString(value) {
|
||||
// Make sure the "returns" is surrounded by a space and all whitespace is exactly one space
|
||||
value = value.replace(/\s/g, " ");
|
||||
value = value.replace(/\(/g, " (").replace(/\)/g, ") ").replace(/\s+/g, " ");
|
||||
value = value.trim();
|
||||
if (value.split(" ")[0] === "event") {
|
||||
return EventFragment.fromString(value.substring(5).trim());
|
||||
}
|
||||
else if (value.split(" ")[0] === "function") {
|
||||
return FunctionFragment.fromString(value.substring(8).trim());
|
||||
}
|
||||
else if (value.split("(")[0].trim() === "constructor") {
|
||||
return ConstructorFragment.fromString(value.trim());
|
||||
}
|
||||
throw new Error("unknown fragment");
|
||||
}
|
||||
static isFragment(value) {
|
||||
return !!(value && value._isFragment);
|
||||
}
|
||||
}
|
||||
export class EventFragment extends Fragment {
|
||||
format(format) {
|
||||
if (!format) {
|
||||
format = FormatTypes.sighash;
|
||||
}
|
||||
if (!FormatTypes[format]) {
|
||||
logger.throwArgumentError("invalid format type", "format", format);
|
||||
}
|
||||
if (format === FormatTypes.json) {
|
||||
return JSON.stringify({
|
||||
type: "event",
|
||||
anonymous: this.anonymous,
|
||||
name: this.name,
|
||||
inputs: this.inputs.map((input) => JSON.parse(input.format(format)))
|
||||
});
|
||||
}
|
||||
let result = "";
|
||||
if (format !== FormatTypes.sighash) {
|
||||
result += "event ";
|
||||
}
|
||||
result += this.name + "(" + this.inputs.map((input) => input.format(format)).join((format === FormatTypes.full) ? ", " : ",") + ") ";
|
||||
if (format !== FormatTypes.sighash) {
|
||||
if (this.anonymous) {
|
||||
result += "anonymous ";
|
||||
}
|
||||
}
|
||||
return result.trim();
|
||||
}
|
||||
static from(value) {
|
||||
if (typeof (value) === "string") {
|
||||
return EventFragment.fromString(value);
|
||||
}
|
||||
return EventFragment.fromObject(value);
|
||||
}
|
||||
static fromObject(value) {
|
||||
if (EventFragment.isEventFragment(value)) {
|
||||
return value;
|
||||
}
|
||||
if (value.type !== "event") {
|
||||
throw new Error("invalid event object - " + value.type);
|
||||
}
|
||||
return new EventFragment(_constructorGuard, {
|
||||
name: verifyIdentifier(value.name),
|
||||
anonymous: value.anonymous,
|
||||
inputs: (value.inputs ? value.inputs.map(ParamType.fromObject) : []),
|
||||
type: "event"
|
||||
});
|
||||
}
|
||||
static fromString(value) {
|
||||
let match = value.match(regexParen);
|
||||
if (!match) {
|
||||
throw new Error("invalid event: " + value);
|
||||
}
|
||||
let anonymous = false;
|
||||
match[3].split(" ").forEach((modifier) => {
|
||||
switch (modifier.trim()) {
|
||||
case "anonymous":
|
||||
anonymous = true;
|
||||
break;
|
||||
case "":
|
||||
break;
|
||||
default:
|
||||
logger.warn("unknown modifier: " + modifier);
|
||||
}
|
||||
});
|
||||
return EventFragment.fromObject({
|
||||
name: match[1].trim(),
|
||||
anonymous: anonymous,
|
||||
inputs: parseParams(match[2], true),
|
||||
type: "event"
|
||||
});
|
||||
}
|
||||
static isEventFragment(value) {
|
||||
return (value && value._isFragment && value.type === "event");
|
||||
}
|
||||
}
|
||||
function parseGas(value, params) {
|
||||
params.gas = null;
|
||||
let comps = value.split("@");
|
||||
if (comps.length !== 1) {
|
||||
if (comps.length > 2) {
|
||||
throw new Error("invalid signature");
|
||||
}
|
||||
if (!comps[1].match(/^[0-9]+$/)) {
|
||||
throw new Error("invalid signature gas");
|
||||
}
|
||||
params.gas = BigNumber.from(comps[1]);
|
||||
return comps[0];
|
||||
}
|
||||
return value;
|
||||
}
|
||||
function parseModifiers(value, params) {
|
||||
params.constant = false;
|
||||
params.payable = false;
|
||||
params.stateMutability = "nonpayable";
|
||||
value.split(" ").forEach((modifier) => {
|
||||
switch (modifier.trim()) {
|
||||
case "constant":
|
||||
params.constant = true;
|
||||
break;
|
||||
case "payable":
|
||||
params.payable = true;
|
||||
params.stateMutability = "payable";
|
||||
break;
|
||||
case "pure":
|
||||
params.constant = true;
|
||||
params.stateMutability = "pure";
|
||||
break;
|
||||
case "view":
|
||||
params.constant = true;
|
||||
params.stateMutability = "view";
|
||||
break;
|
||||
case "external":
|
||||
case "public":
|
||||
case "":
|
||||
break;
|
||||
default:
|
||||
console.log("unknown modifier: " + modifier);
|
||||
}
|
||||
});
|
||||
}
|
||||
function verifyState(value) {
|
||||
let result = {
|
||||
constant: false,
|
||||
payable: true,
|
||||
stateMutability: "payable"
|
||||
};
|
||||
if (value.stateMutability != null) {
|
||||
result.stateMutability = value.stateMutability;
|
||||
result.constant = (result.stateMutability === "view" || result.stateMutability === "pure");
|
||||
if (value.constant != null) {
|
||||
if ((!!value.constant) !== result.constant) {
|
||||
throw new Error("cannot have constant function with mutability " + result.stateMutability);
|
||||
}
|
||||
}
|
||||
result.payable = (result.stateMutability === "payable");
|
||||
if (value.payable != null) {
|
||||
if ((!!value.payable) !== result.payable) {
|
||||
throw new Error("cannot have payable function with mutability " + result.stateMutability);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (value.payable != null) {
|
||||
result.payable = !!value.payable;
|
||||
result.stateMutability = (result.payable ? "payable" : "nonpayable");
|
||||
result.constant = !result.payable;
|
||||
if (value.constant != null && (value.constant !== result.constant)) {
|
||||
throw new Error("cannot have constant payable function");
|
||||
}
|
||||
}
|
||||
else if (value.constant != null) {
|
||||
result.constant = !!value.constant;
|
||||
result.payable = !result.constant;
|
||||
result.stateMutability = (result.constant ? "view" : "payable");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
export class ConstructorFragment extends Fragment {
|
||||
format(format) {
|
||||
if (!format) {
|
||||
format = FormatTypes.sighash;
|
||||
}
|
||||
if (!FormatTypes[format]) {
|
||||
logger.throwArgumentError("invalid format type", "format", format);
|
||||
}
|
||||
if (format === FormatTypes.json) {
|
||||
return JSON.stringify({
|
||||
type: "constructor",
|
||||
stateMutability: ((this.stateMutability !== "nonpayable") ? this.stateMutability : undefined),
|
||||
payble: this.payable,
|
||||
gas: (this.gas ? this.gas.toNumber() : undefined),
|
||||
inputs: this.inputs.map((input) => JSON.parse(input.format(format)))
|
||||
});
|
||||
}
|
||||
if (format === FormatTypes.sighash) {
|
||||
logger.throwError("cannot format a constructor for sighash", Logger.errors.UNSUPPORTED_OPERATION, {
|
||||
operation: "format(sighash)"
|
||||
});
|
||||
}
|
||||
let result = "constructor(" + this.inputs.map((input) => input.format(format)).join((format === FormatTypes.full) ? ", " : ",") + ") ";
|
||||
if (this.stateMutability && this.stateMutability !== "nonpayable") {
|
||||
result += this.stateMutability + " ";
|
||||
}
|
||||
return result.trim();
|
||||
}
|
||||
static from(value) {
|
||||
if (typeof (value) === "string") {
|
||||
return ConstructorFragment.fromString(value);
|
||||
}
|
||||
return ConstructorFragment.fromObject(value);
|
||||
}
|
||||
static fromObject(value) {
|
||||
if (ConstructorFragment.isConstructorFragment(value)) {
|
||||
return value;
|
||||
}
|
||||
if (value.type !== "constructor") {
|
||||
throw new Error("invalid constructor object - " + value.type);
|
||||
}
|
||||
let state = verifyState(value);
|
||||
if (state.constant) {
|
||||
throw new Error("constructor cannot be constant");
|
||||
}
|
||||
return new ConstructorFragment(_constructorGuard, {
|
||||
type: value.type,
|
||||
inputs: (value.inputs ? value.inputs.map(ParamType.fromObject) : []),
|
||||
payable: state.payable,
|
||||
gas: (value.gas ? BigNumber.from(value.gas) : null)
|
||||
});
|
||||
}
|
||||
static fromString(value) {
|
||||
let params = { type: "constructor" };
|
||||
value = parseGas(value, params);
|
||||
let parens = value.match(regexParen);
|
||||
if (!parens) {
|
||||
throw new Error("invalid constructor: " + value);
|
||||
}
|
||||
if (parens[1].trim() !== "constructor") {
|
||||
throw new Error("invalid constructor");
|
||||
}
|
||||
params.inputs = parseParams(parens[2].trim(), false);
|
||||
parseModifiers(parens[3].trim(), params);
|
||||
return ConstructorFragment.fromObject(params);
|
||||
}
|
||||
static isConstructorFragment(value) {
|
||||
return (value && value._isFragment && value.type === "constructor");
|
||||
}
|
||||
}
|
||||
export class FunctionFragment extends ConstructorFragment {
|
||||
format(format) {
|
||||
if (!format) {
|
||||
format = FormatTypes.sighash;
|
||||
}
|
||||
if (!FormatTypes[format]) {
|
||||
logger.throwArgumentError("invalid format type", "format", format);
|
||||
}
|
||||
if (format === FormatTypes.json) {
|
||||
return JSON.stringify({
|
||||
type: "function",
|
||||
name: this.name,
|
||||
constant: this.constant,
|
||||
stateMutability: ((this.stateMutability !== "nonpayable") ? this.stateMutability : undefined),
|
||||
payble: this.payable,
|
||||
gas: (this.gas ? this.gas.toNumber() : undefined),
|
||||
inputs: this.inputs.map((input) => JSON.parse(input.format(format))),
|
||||
ouputs: this.outputs.map((output) => JSON.parse(output.format(format))),
|
||||
});
|
||||
}
|
||||
let result = "";
|
||||
if (format !== FormatTypes.sighash) {
|
||||
result += "function ";
|
||||
}
|
||||
result += this.name + "(" + this.inputs.map((input) => input.format(format)).join((format === FormatTypes.full) ? ", " : ",") + ") ";
|
||||
if (format !== FormatTypes.sighash) {
|
||||
if (this.stateMutability) {
|
||||
if (this.stateMutability !== "nonpayable") {
|
||||
result += (this.stateMutability + " ");
|
||||
}
|
||||
}
|
||||
else if (this.constant) {
|
||||
result += "view ";
|
||||
}
|
||||
if (this.outputs && this.outputs.length) {
|
||||
result += "returns (" + this.outputs.map((output) => output.format(format)).join(", ") + ") ";
|
||||
}
|
||||
if (this.gas != null) {
|
||||
result += "@" + this.gas.toString() + " ";
|
||||
}
|
||||
}
|
||||
return result.trim();
|
||||
}
|
||||
static from(value) {
|
||||
if (typeof (value) === "string") {
|
||||
return FunctionFragment.fromString(value);
|
||||
}
|
||||
return FunctionFragment.fromObject(value);
|
||||
}
|
||||
static fromObject(value) {
|
||||
if (FunctionFragment.isFunctionFragment(value)) {
|
||||
return value;
|
||||
}
|
||||
if (value.type !== "function") {
|
||||
throw new Error("invalid function object - " + value.type);
|
||||
}
|
||||
let state = verifyState(value);
|
||||
return new FunctionFragment(_constructorGuard, {
|
||||
type: value.type,
|
||||
name: verifyIdentifier(value.name),
|
||||
constant: state.constant,
|
||||
inputs: (value.inputs ? value.inputs.map(ParamType.fromObject) : []),
|
||||
outputs: (value.outputs ? value.outputs.map(ParamType.fromObject) : []),
|
||||
payable: state.payable,
|
||||
stateMutability: state.stateMutability,
|
||||
gas: (value.gas ? BigNumber.from(value.gas) : null)
|
||||
});
|
||||
}
|
||||
static fromString(value) {
|
||||
let params = { type: "function" };
|
||||
value = parseGas(value, params);
|
||||
let comps = value.split(" returns ");
|
||||
if (comps.length > 2) {
|
||||
throw new Error("invalid function");
|
||||
}
|
||||
let parens = comps[0].match(regexParen);
|
||||
if (!parens) {
|
||||
throw new Error("invalid signature");
|
||||
}
|
||||
params.name = parens[1].trim();
|
||||
if (!params.name.match(regexIdentifier)) {
|
||||
throw new Error("invalid identifier: '" + params.name + "'");
|
||||
}
|
||||
params.inputs = parseParams(parens[2], false);
|
||||
parseModifiers(parens[3].trim(), params);
|
||||
// We have outputs
|
||||
if (comps.length > 1) {
|
||||
let returns = comps[1].match(regexParen);
|
||||
if (returns[1].trim() != "" || returns[3].trim() != "") {
|
||||
throw new Error("unexpected tokens");
|
||||
}
|
||||
params.outputs = parseParams(returns[2], false);
|
||||
}
|
||||
else {
|
||||
params.outputs = [];
|
||||
}
|
||||
return FunctionFragment.fromObject(params);
|
||||
}
|
||||
static isFunctionFragment(value) {
|
||||
return (value && value._isFragment && value.type === "function");
|
||||
}
|
||||
}
|
||||
//export class ErrorFragment extends Fragment {
|
||||
//}
|
||||
//export class StructFragment extends Fragment {
|
||||
//}
|
||||
function verifyType(type) {
|
||||
// These need to be transformed to their full description
|
||||
if (type.match(/^uint($|[^1-9])/)) {
|
||||
type = "uint256" + type.substring(4);
|
||||
}
|
||||
else if (type.match(/^int($|[^1-9])/)) {
|
||||
type = "int256" + type.substring(3);
|
||||
}
|
||||
// @TODO: more verification
|
||||
return type;
|
||||
}
|
||||
const regexIdentifier = new RegExp("^[A-Za-z_][A-Za-z0-9_]*$");
|
||||
function verifyIdentifier(value) {
|
||||
if (!value || !value.match(regexIdentifier)) {
|
||||
throw new Error("invalid identifier: '" + value + "'");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
const regexParen = new RegExp("^([^)(]*)\\((.*)\\)([^)(]*)$");
|
||||
function splitNesting(value) {
|
||||
value = value.trim();
|
||||
let result = [];
|
||||
let accum = "";
|
||||
let depth = 0;
|
||||
for (let offset = 0; offset < value.length; offset++) {
|
||||
let c = value[offset];
|
||||
if (c === "," && depth === 0) {
|
||||
result.push(accum);
|
||||
accum = "";
|
||||
}
|
||||
else {
|
||||
accum += c;
|
||||
if (c === "(") {
|
||||
depth++;
|
||||
}
|
||||
else if (c === ")") {
|
||||
depth--;
|
||||
if (depth === -1) {
|
||||
throw new Error("unbalanced parenthsis");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (accum) {
|
||||
result.push(accum);
|
||||
}
|
||||
return result;
|
||||
}
|
5
packages/abi/lib.esm/index.js
Normal file
5
packages/abi/lib.esm/index.js
Normal file
@ -0,0 +1,5 @@
|
||||
"use strict";
|
||||
import { ConstructorFragment, EventFragment, FormatTypes, Fragment, FunctionFragment, ParamType } from "./fragments";
|
||||
import { AbiCoder, defaultAbiCoder } from "./abi-coder";
|
||||
import { Indexed, Interface } from "./interface";
|
||||
export { ConstructorFragment, EventFragment, Fragment, FunctionFragment, ParamType, FormatTypes, AbiCoder, defaultAbiCoder, Interface, Indexed };
|
342
packages/abi/lib.esm/interface.js
Normal file
342
packages/abi/lib.esm/interface.js
Normal file
@ -0,0 +1,342 @@
|
||||
"use strict";
|
||||
import { getAddress } from "@ethersproject/address";
|
||||
import { BigNumber } from "@ethersproject/bignumber";
|
||||
import { arrayify, concat, hexDataSlice, hexlify, hexZeroPad, isHexString } from "@ethersproject/bytes";
|
||||
import { id } from "@ethersproject/hash";
|
||||
import { keccak256 } from "@ethersproject/keccak256";
|
||||
import { defineReadOnly, Description, getStatic } from "@ethersproject/properties";
|
||||
import { defaultAbiCoder } from "./abi-coder";
|
||||
import { ConstructorFragment, EventFragment, Fragment, FunctionFragment, ParamType } from "./fragments";
|
||||
import { Logger } from "@ethersproject/logger";
|
||||
import { version } from "./_version";
|
||||
const logger = new Logger(version);
|
||||
export class LogDescription extends Description {
|
||||
}
|
||||
export class TransactionDescription extends Description {
|
||||
}
|
||||
export class Indexed extends Description {
|
||||
static isIndexed(value) {
|
||||
return !!(value && value._isIndexed);
|
||||
}
|
||||
}
|
||||
export class Result {
|
||||
}
|
||||
export class Interface {
|
||||
constructor(fragments) {
|
||||
logger.checkNew(new.target, Interface);
|
||||
let abi = [];
|
||||
if (typeof (fragments) === "string") {
|
||||
abi = JSON.parse(fragments);
|
||||
}
|
||||
else {
|
||||
abi = fragments;
|
||||
}
|
||||
defineReadOnly(this, "fragments", abi.map((fragment) => {
|
||||
return Fragment.from(fragment);
|
||||
}).filter((fragment) => (fragment != null)));
|
||||
defineReadOnly(this, "_abiCoder", getStatic((new.target), "getAbiCoder")());
|
||||
defineReadOnly(this, "functions", {});
|
||||
defineReadOnly(this, "errors", {});
|
||||
defineReadOnly(this, "events", {});
|
||||
defineReadOnly(this, "structs", {});
|
||||
// Add all fragments by their signature
|
||||
this.fragments.forEach((fragment) => {
|
||||
let bucket = null;
|
||||
switch (fragment.type) {
|
||||
case "constructor":
|
||||
if (this.deploy) {
|
||||
logger.warn("duplicate definition - constructor");
|
||||
return;
|
||||
}
|
||||
defineReadOnly(this, "deploy", fragment);
|
||||
return;
|
||||
case "function":
|
||||
bucket = this.functions;
|
||||
break;
|
||||
case "event":
|
||||
bucket = this.events;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
let signature = fragment.format();
|
||||
if (bucket[signature]) {
|
||||
logger.warn("duplicate definition - " + signature);
|
||||
return;
|
||||
}
|
||||
bucket[signature] = fragment;
|
||||
});
|
||||
// Add any fragments with a unique name by its name (sans signature parameters)
|
||||
[this.events, this.functions].forEach((bucket) => {
|
||||
let count = getNameCount(bucket);
|
||||
Object.keys(bucket).forEach((signature) => {
|
||||
let fragment = bucket[signature];
|
||||
if (count[fragment.name] !== 1) {
|
||||
logger.warn("duplicate definition - " + fragment.name);
|
||||
return;
|
||||
}
|
||||
bucket[fragment.name] = fragment;
|
||||
});
|
||||
});
|
||||
// If we do not have a constructor use the default "constructor() payable"
|
||||
if (!this.deploy) {
|
||||
defineReadOnly(this, "deploy", ConstructorFragment.from({ type: "constructor" }));
|
||||
}
|
||||
defineReadOnly(this, "_isInterface", true);
|
||||
}
|
||||
static getAbiCoder() {
|
||||
return defaultAbiCoder;
|
||||
}
|
||||
static getAddress(address) {
|
||||
return getAddress(address);
|
||||
}
|
||||
_sighashify(functionFragment) {
|
||||
return hexDataSlice(id(functionFragment.format()), 0, 4);
|
||||
}
|
||||
_topicify(eventFragment) {
|
||||
return id(eventFragment.format());
|
||||
}
|
||||
getFunction(nameOrSignatureOrSighash) {
|
||||
if (isHexString(nameOrSignatureOrSighash)) {
|
||||
return getFragment(nameOrSignatureOrSighash, this.getSighash.bind(this), this.functions);
|
||||
}
|
||||
// It is a bare name, look up the function (will return null if ambiguous)
|
||||
if (nameOrSignatureOrSighash.indexOf("(") === -1) {
|
||||
return (this.functions[nameOrSignatureOrSighash.trim()] || null);
|
||||
}
|
||||
// Normlize the signature and lookup the function
|
||||
return this.functions[FunctionFragment.fromString(nameOrSignatureOrSighash).format()];
|
||||
}
|
||||
getEvent(nameOrSignatureOrTopic) {
|
||||
if (isHexString(nameOrSignatureOrTopic)) {
|
||||
return getFragment(nameOrSignatureOrTopic, this.getEventTopic.bind(this), this.events);
|
||||
}
|
||||
// It is a bare name, look up the function (will return null if ambiguous)
|
||||
if (nameOrSignatureOrTopic.indexOf("(") === -1) {
|
||||
return this.events[nameOrSignatureOrTopic];
|
||||
}
|
||||
return this.events[EventFragment.fromString(nameOrSignatureOrTopic).format()];
|
||||
}
|
||||
getSighash(functionFragment) {
|
||||
if (typeof (functionFragment) === "string") {
|
||||
functionFragment = this.getFunction(functionFragment);
|
||||
}
|
||||
return this._sighashify(functionFragment);
|
||||
}
|
||||
getEventTopic(eventFragment) {
|
||||
if (typeof (eventFragment) === "string") {
|
||||
eventFragment = this.getEvent(eventFragment);
|
||||
}
|
||||
return this._topicify(eventFragment);
|
||||
}
|
||||
_encodeParams(params, values) {
|
||||
return this._abiCoder.encode(params, values);
|
||||
}
|
||||
encodeDeploy(values) {
|
||||
return this._encodeParams(this.deploy.inputs, values || []);
|
||||
}
|
||||
encodeFunctionData(functionFragment, values) {
|
||||
if (typeof (functionFragment) === "string") {
|
||||
functionFragment = this.getFunction(functionFragment);
|
||||
}
|
||||
return hexlify(concat([
|
||||
this.getSighash(functionFragment),
|
||||
this._encodeParams(functionFragment.inputs, values || [])
|
||||
]));
|
||||
}
|
||||
decodeFunctionResult(functionFragment, data) {
|
||||
if (typeof (functionFragment) === "string") {
|
||||
functionFragment = this.getFunction(functionFragment);
|
||||
}
|
||||
let bytes = arrayify(data);
|
||||
let reason = null;
|
||||
let errorSignature = null;
|
||||
switch (bytes.length % this._abiCoder._getWordSize()) {
|
||||
case 0:
|
||||
try {
|
||||
return this._abiCoder.decode(functionFragment.outputs, bytes);
|
||||
}
|
||||
catch (error) { }
|
||||
break;
|
||||
case 4:
|
||||
if (hexlify(bytes.slice(0, 4)) === "0x08c379a0") {
|
||||
errorSignature = "Error(string)";
|
||||
reason = this._abiCoder.decode(["string"], bytes.slice(4));
|
||||
}
|
||||
break;
|
||||
}
|
||||
return logger.throwError("call revert exception", Logger.errors.CALL_EXCEPTION, {
|
||||
method: functionFragment.format(),
|
||||
errorSignature: errorSignature,
|
||||
errorArgs: [reason],
|
||||
reason: reason
|
||||
});
|
||||
}
|
||||
encodeFilterTopics(eventFragment, values) {
|
||||
if (typeof (eventFragment) === "string") {
|
||||
eventFragment = this.getEvent(eventFragment);
|
||||
}
|
||||
if (values.length > eventFragment.inputs.length) {
|
||||
logger.throwError("too many arguments for " + eventFragment.format(), Logger.errors.UNEXPECTED_ARGUMENT, {
|
||||
argument: "values",
|
||||
value: values
|
||||
});
|
||||
}
|
||||
let topics = [];
|
||||
if (!eventFragment.anonymous) {
|
||||
topics.push(this.getEventTopic(eventFragment));
|
||||
}
|
||||
values.forEach((value, index) => {
|
||||
let param = eventFragment.inputs[index];
|
||||
if (!param.indexed) {
|
||||
if (value != null) {
|
||||
logger.throwArgumentError("cannot filter non-indexed parameters; must be null", ("contract." + param.name), value);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (value == null) {
|
||||
topics.push(null);
|
||||
}
|
||||
else if (param.type === "string") {
|
||||
topics.push(id(value));
|
||||
}
|
||||
else if (param.type === "bytes") {
|
||||
topics.push(keccak256(hexlify(value)));
|
||||
}
|
||||
else if (param.type.indexOf("[") !== -1 || param.type.substring(0, 5) === "tuple") {
|
||||
logger.throwArgumentError("filtering with tuples or arrays not supported", ("contract." + param.name), value);
|
||||
}
|
||||
else {
|
||||
// Check addresses are valid
|
||||
if (param.type === "address") {
|
||||
this._abiCoder.encode(["address"], [value]);
|
||||
}
|
||||
topics.push(hexZeroPad(hexlify(value), 32));
|
||||
}
|
||||
});
|
||||
// Trim off trailing nulls
|
||||
while (topics.length && topics[topics.length - 1] === null) {
|
||||
topics.pop();
|
||||
}
|
||||
return topics;
|
||||
}
|
||||
decodeEventLog(eventFragment, data, topics) {
|
||||
if (typeof (eventFragment) === "string") {
|
||||
eventFragment = this.getEvent(eventFragment);
|
||||
}
|
||||
if (topics != null && !eventFragment.anonymous) {
|
||||
let topicHash = this.getEventTopic(eventFragment);
|
||||
if (!isHexString(topics[0], 32) || topics[0].toLowerCase() !== topicHash) {
|
||||
logger.throwError("fragment/topic mismatch", Logger.errors.INVALID_ARGUMENT, { argument: "topics[0]", expected: topicHash, value: topics[0] });
|
||||
}
|
||||
topics = topics.slice(1);
|
||||
}
|
||||
let indexed = [];
|
||||
let nonIndexed = [];
|
||||
let dynamic = [];
|
||||
eventFragment.inputs.forEach((param, index) => {
|
||||
if (param.indexed) {
|
||||
if (param.type === "string" || param.type === "bytes" || param.baseType === "tuple" || param.baseType === "array") {
|
||||
indexed.push(ParamType.fromObject({ type: "bytes32", name: param.name }));
|
||||
dynamic.push(true);
|
||||
}
|
||||
else {
|
||||
indexed.push(param);
|
||||
dynamic.push(false);
|
||||
}
|
||||
}
|
||||
else {
|
||||
nonIndexed.push(param);
|
||||
dynamic.push(false);
|
||||
}
|
||||
});
|
||||
let resultIndexed = (topics != null) ? this._abiCoder.decode(indexed, concat(topics)) : null;
|
||||
let resultNonIndexed = this._abiCoder.decode(nonIndexed, data);
|
||||
let result = [];
|
||||
let nonIndexedIndex = 0, indexedIndex = 0;
|
||||
eventFragment.inputs.forEach((param, index) => {
|
||||
if (param.indexed) {
|
||||
if (resultIndexed == null) {
|
||||
result[index] = new Indexed({ _isIndexed: true, hash: null });
|
||||
}
|
||||
else if (dynamic[index]) {
|
||||
result[index] = new Indexed({ _isIndexed: true, hash: resultIndexed[indexedIndex++] });
|
||||
}
|
||||
else {
|
||||
result[index] = resultIndexed[indexedIndex++];
|
||||
}
|
||||
}
|
||||
else {
|
||||
result[index] = resultNonIndexed[nonIndexedIndex++];
|
||||
}
|
||||
//if (param.name && result[param.name] == null) { result[param.name] = result[index]; }
|
||||
});
|
||||
return result;
|
||||
}
|
||||
parseTransaction(tx) {
|
||||
let fragment = this.getFunction(tx.data.substring(0, 10).toLowerCase());
|
||||
if (!fragment) {
|
||||
return null;
|
||||
}
|
||||
return new TransactionDescription({
|
||||
args: this._abiCoder.decode(fragment.inputs, "0x" + tx.data.substring(10)),
|
||||
functionFragment: fragment,
|
||||
name: fragment.name,
|
||||
signature: fragment.format(),
|
||||
sighash: this.getSighash(fragment),
|
||||
value: BigNumber.from(tx.value || "0"),
|
||||
});
|
||||
}
|
||||
parseLog(log) {
|
||||
let fragment = this.getEvent(log.topics[0]);
|
||||
if (!fragment || fragment.anonymous) {
|
||||
return null;
|
||||
}
|
||||
// @TODO: If anonymous, and the only method, and the input count matches, should we parse?
|
||||
return new LogDescription({
|
||||
eventFragment: fragment,
|
||||
name: fragment.name,
|
||||
signature: fragment.format(),
|
||||
topic: this.getEventTopic(fragment),
|
||||
values: this.decodeEventLog(fragment, log.data, log.topics)
|
||||
});
|
||||
}
|
||||
/*
|
||||
static from(value: Array<Fragment | string | JsonAbi> | string | Interface) {
|
||||
if (Interface.isInterface(value)) {
|
||||
return value;
|
||||
}
|
||||
if (typeof(value) === "string") {
|
||||
return new Interface(JSON.parse(value));
|
||||
}
|
||||
return new Interface(value);
|
||||
}
|
||||
*/
|
||||
static isInterface(value) {
|
||||
return !!(value && value._isInterface);
|
||||
}
|
||||
}
|
||||
function getFragment(hash, calcFunc, items) {
|
||||
for (let signature in items) {
|
||||
if (signature.indexOf("(") === -1) {
|
||||
continue;
|
||||
}
|
||||
let fragment = items[signature];
|
||||
if (calcFunc(fragment) === hash) {
|
||||
return fragment;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
function getNameCount(fragments) {
|
||||
let unique = {};
|
||||
// Count each name
|
||||
for (let signature in fragments) {
|
||||
let name = fragments[signature].name;
|
||||
if (!unique[name]) {
|
||||
unique[name] = 0;
|
||||
}
|
||||
unique[name]++;
|
||||
}
|
||||
return unique;
|
||||
}
|
1
packages/abi/lib/_version.d.ts
vendored
Normal file
1
packages/abi/lib/_version.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
||||
export declare const version = "abi/5.0.0-beta.136";
|
15
packages/abi/lib/abi-coder.d.ts
vendored
Normal file
15
packages/abi/lib/abi-coder.d.ts
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
import { BytesLike } from "@ethersproject/bytes";
|
||||
import { Coder, Reader, Writer } from "./coders/abstract-coder";
|
||||
import { ParamType } from "./fragments";
|
||||
export declare type CoerceFunc = (type: string, value: any) => any;
|
||||
export declare class AbiCoder {
|
||||
readonly coerceFunc: CoerceFunc;
|
||||
constructor(coerceFunc?: CoerceFunc);
|
||||
_getCoder(param: ParamType): Coder;
|
||||
_getWordSize(): number;
|
||||
_getReader(data: Uint8Array): Reader;
|
||||
_getWriter(): Writer;
|
||||
encode(types: Array<string | ParamType>, values: Array<any>): string;
|
||||
decode(types: Array<string | ParamType>, data: BytesLike): any;
|
||||
}
|
||||
export declare const defaultAbiCoder: AbiCoder;
|
41
packages/abi/lib/coders/abstract-coder.d.ts
vendored
Normal file
41
packages/abi/lib/coders/abstract-coder.d.ts
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
import { BytesLike } from "@ethersproject/bytes";
|
||||
import { BigNumber, BigNumberish } from "@ethersproject/bignumber";
|
||||
export declare type CoerceFunc = (type: string, value: any) => any;
|
||||
export declare abstract class Coder {
|
||||
readonly name: string;
|
||||
readonly type: string;
|
||||
readonly localName: string;
|
||||
readonly dynamic: boolean;
|
||||
constructor(name: string, type: string, localName: string, dynamic: boolean);
|
||||
_throwError(message: string, value: any): void;
|
||||
abstract encode(writer: Writer, value: any): number;
|
||||
abstract decode(reader: Reader): any;
|
||||
}
|
||||
export declare class Writer {
|
||||
readonly wordSize: number;
|
||||
_data: Uint8Array;
|
||||
_padding: Uint8Array;
|
||||
constructor(wordSize?: number);
|
||||
readonly data: string;
|
||||
readonly length: number;
|
||||
_writeData(data: Uint8Array): number;
|
||||
writeBytes(value: BytesLike): number;
|
||||
_getValue(value: BigNumberish): Uint8Array;
|
||||
writeValue(value: BigNumberish): number;
|
||||
writeUpdatableValue(): (value: BigNumberish) => void;
|
||||
}
|
||||
export declare class Reader {
|
||||
readonly wordSize: number;
|
||||
readonly _data: Uint8Array;
|
||||
readonly _coerceFunc: CoerceFunc;
|
||||
_offset: number;
|
||||
constructor(data: BytesLike, wordSize?: number, coerceFunc?: CoerceFunc);
|
||||
readonly data: string;
|
||||
readonly consumed: number;
|
||||
static coerce(name: string, value: any): any;
|
||||
coerce(name: string, value: any): any;
|
||||
_peekBytes(offset: number, length: number): Uint8Array;
|
||||
subReader(offset: number): Reader;
|
||||
readBytes(length: number): Uint8Array;
|
||||
readValue(): BigNumber;
|
||||
}
|
133
packages/abi/lib/coders/abstract-coder.js
Normal file
133
packages/abi/lib/coders/abstract-coder.js
Normal file
@ -0,0 +1,133 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var bytes_1 = require("@ethersproject/bytes");
|
||||
var bignumber_1 = require("@ethersproject/bignumber");
|
||||
var properties_1 = require("@ethersproject/properties");
|
||||
var logger_1 = require("@ethersproject/logger");
|
||||
var _version_1 = require("../_version");
|
||||
var logger = new logger_1.Logger(_version_1.version);
|
||||
var Coder = /** @class */ (function () {
|
||||
function Coder(name, type, localName, dynamic) {
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
this.localName = localName;
|
||||
this.dynamic = dynamic;
|
||||
}
|
||||
Coder.prototype._throwError = function (message, value) {
|
||||
logger.throwArgumentError(message, this.localName, value);
|
||||
};
|
||||
return Coder;
|
||||
}());
|
||||
exports.Coder = Coder;
|
||||
var Writer = /** @class */ (function () {
|
||||
function Writer(wordSize) {
|
||||
properties_1.defineReadOnly(this, "wordSize", wordSize || 32);
|
||||
this._data = bytes_1.arrayify([]);
|
||||
this._padding = new Uint8Array(wordSize);
|
||||
}
|
||||
Object.defineProperty(Writer.prototype, "data", {
|
||||
get: function () { return bytes_1.hexlify(this._data); },
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
Object.defineProperty(Writer.prototype, "length", {
|
||||
get: function () { return this._data.length; },
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
Writer.prototype._writeData = function (data) {
|
||||
this._data = bytes_1.concat([this._data, data]);
|
||||
return data.length;
|
||||
};
|
||||
// Arrayish items; padded on the right to wordSize
|
||||
Writer.prototype.writeBytes = function (value) {
|
||||
var bytes = bytes_1.arrayify(value);
|
||||
if (bytes.length % this.wordSize) {
|
||||
bytes = bytes_1.concat([bytes, this._padding.slice(bytes.length % this.wordSize)]);
|
||||
}
|
||||
return this._writeData(bytes);
|
||||
};
|
||||
Writer.prototype._getValue = function (value) {
|
||||
var bytes = bytes_1.arrayify(bignumber_1.BigNumber.from(value));
|
||||
if (bytes.length > this.wordSize) {
|
||||
logger.throwError("value out-of-bounds", logger_1.Logger.errors.BUFFER_OVERRUN, {
|
||||
length: this.wordSize,
|
||||
offset: bytes.length
|
||||
});
|
||||
}
|
||||
if (bytes.length % this.wordSize) {
|
||||
bytes = bytes_1.concat([this._padding.slice(bytes.length % this.wordSize), bytes]);
|
||||
}
|
||||
return bytes;
|
||||
};
|
||||
// BigNumberish items; padded on the left to wordSize
|
||||
Writer.prototype.writeValue = function (value) {
|
||||
return this._writeData(this._getValue(value));
|
||||
};
|
||||
Writer.prototype.writeUpdatableValue = function () {
|
||||
var _this = this;
|
||||
var offset = this.length;
|
||||
this.writeValue(0);
|
||||
return function (value) {
|
||||
_this._data.set(_this._getValue(value), offset);
|
||||
};
|
||||
};
|
||||
return Writer;
|
||||
}());
|
||||
exports.Writer = Writer;
|
||||
var Reader = /** @class */ (function () {
|
||||
function Reader(data, wordSize, coerceFunc) {
|
||||
properties_1.defineReadOnly(this, "_data", bytes_1.arrayify(data));
|
||||
properties_1.defineReadOnly(this, "wordSize", wordSize || 32);
|
||||
properties_1.defineReadOnly(this, "_coerceFunc", coerceFunc);
|
||||
this._offset = 0;
|
||||
}
|
||||
Object.defineProperty(Reader.prototype, "data", {
|
||||
get: function () { return bytes_1.hexlify(this._data); },
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
Object.defineProperty(Reader.prototype, "consumed", {
|
||||
get: function () { return this._offset; },
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
// The default Coerce function
|
||||
Reader.coerce = function (name, value) {
|
||||
var match = name.match("^u?int([0-9]+)$");
|
||||
if (match && parseInt(match[1]) <= 48) {
|
||||
value = value.toNumber();
|
||||
}
|
||||
return value;
|
||||
};
|
||||
Reader.prototype.coerce = function (name, value) {
|
||||
if (this._coerceFunc) {
|
||||
return this._coerceFunc(name, value);
|
||||
}
|
||||
return Reader.coerce(name, value);
|
||||
};
|
||||
Reader.prototype._peekBytes = function (offset, length) {
|
||||
var alignedLength = Math.ceil(length / this.wordSize) * this.wordSize;
|
||||
if (this._offset + alignedLength > this._data.length) {
|
||||
logger.throwError("data out-of-bounds", logger_1.Logger.errors.BUFFER_OVERRUN, {
|
||||
length: this._data.length,
|
||||
offset: this._offset + alignedLength
|
||||
});
|
||||
}
|
||||
return this._data.slice(this._offset, this._offset + alignedLength);
|
||||
};
|
||||
Reader.prototype.subReader = function (offset) {
|
||||
return new Reader(this._data.slice(this._offset + offset), this.wordSize, this._coerceFunc);
|
||||
};
|
||||
Reader.prototype.readBytes = function (length) {
|
||||
var bytes = this._peekBytes(0, length);
|
||||
this._offset += bytes.length;
|
||||
// @TODO: Make sure the length..end bytes are all 0?
|
||||
return bytes.slice(0, length);
|
||||
};
|
||||
Reader.prototype.readValue = function () {
|
||||
return bignumber_1.BigNumber.from(this.readBytes(this.wordSize));
|
||||
};
|
||||
return Reader;
|
||||
}());
|
||||
exports.Reader = Reader;
|
6
packages/abi/lib/coders/address.d.ts
vendored
Normal file
6
packages/abi/lib/coders/address.d.ts
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
import { Coder, Reader, Writer } from "./abstract-coder";
|
||||
export declare class AddressCoder extends Coder {
|
||||
constructor(localName: string);
|
||||
encode(writer: Writer, value: string): number;
|
||||
decode(reader: Reader): any;
|
||||
}
|
38
packages/abi/lib/coders/address.js
Normal file
38
packages/abi/lib/coders/address.js
Normal file
@ -0,0 +1,38 @@
|
||||
"use strict";
|
||||
var __extends = (this && this.__extends) || (function () {
|
||||
var extendStatics = function (d, b) {
|
||||
extendStatics = Object.setPrototypeOf ||
|
||||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
||||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
|
||||
return extendStatics(d, b);
|
||||
};
|
||||
return function (d, b) {
|
||||
extendStatics(d, b);
|
||||
function __() { this.constructor = d; }
|
||||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||||
};
|
||||
})();
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var address_1 = require("@ethersproject/address");
|
||||
var bytes_1 = require("@ethersproject/bytes");
|
||||
var abstract_coder_1 = require("./abstract-coder");
|
||||
var AddressCoder = /** @class */ (function (_super) {
|
||||
__extends(AddressCoder, _super);
|
||||
function AddressCoder(localName) {
|
||||
return _super.call(this, "address", "address", localName, false) || this;
|
||||
}
|
||||
AddressCoder.prototype.encode = function (writer, value) {
|
||||
try {
|
||||
address_1.getAddress(value);
|
||||
}
|
||||
catch (error) {
|
||||
this._throwError(error.message, value);
|
||||
}
|
||||
return writer.writeValue(value);
|
||||
};
|
||||
AddressCoder.prototype.decode = function (reader) {
|
||||
return address_1.getAddress(bytes_1.hexZeroPad(reader.readValue().toHexString(), 20));
|
||||
};
|
||||
return AddressCoder;
|
||||
}(abstract_coder_1.Coder));
|
||||
exports.AddressCoder = AddressCoder;
|
7
packages/abi/lib/coders/anonymous.d.ts
vendored
Normal file
7
packages/abi/lib/coders/anonymous.d.ts
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
import { Coder, Reader, Writer } from "./abstract-coder";
|
||||
export declare class AnonymousCoder extends Coder {
|
||||
private coder;
|
||||
constructor(coder: Coder);
|
||||
encode(writer: Writer, value: any): number;
|
||||
decode(reader: Reader): any;
|
||||
}
|
33
packages/abi/lib/coders/anonymous.js
Normal file
33
packages/abi/lib/coders/anonymous.js
Normal file
@ -0,0 +1,33 @@
|
||||
"use strict";
|
||||
var __extends = (this && this.__extends) || (function () {
|
||||
var extendStatics = function (d, b) {
|
||||
extendStatics = Object.setPrototypeOf ||
|
||||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
||||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
|
||||
return extendStatics(d, b);
|
||||
};
|
||||
return function (d, b) {
|
||||
extendStatics(d, b);
|
||||
function __() { this.constructor = d; }
|
||||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||||
};
|
||||
})();
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var abstract_coder_1 = require("./abstract-coder");
|
||||
// Clones the functionality of an existing Coder, but without a localName
|
||||
var AnonymousCoder = /** @class */ (function (_super) {
|
||||
__extends(AnonymousCoder, _super);
|
||||
function AnonymousCoder(coder) {
|
||||
var _this = _super.call(this, coder.name, coder.type, undefined, coder.dynamic) || this;
|
||||
_this.coder = coder;
|
||||
return _this;
|
||||
}
|
||||
AnonymousCoder.prototype.encode = function (writer, value) {
|
||||
return this.coder.encode(writer, value);
|
||||
};
|
||||
AnonymousCoder.prototype.decode = function (reader) {
|
||||
return this.coder.decode(reader);
|
||||
};
|
||||
return AnonymousCoder;
|
||||
}(abstract_coder_1.Coder));
|
||||
exports.AnonymousCoder = AnonymousCoder;
|
10
packages/abi/lib/coders/array.d.ts
vendored
Normal file
10
packages/abi/lib/coders/array.d.ts
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
import { Coder, Reader, Writer } from "./abstract-coder";
|
||||
export declare function pack(writer: Writer, coders: Array<Coder>, values: Array<any>): number;
|
||||
export declare function unpack(reader: Reader, coders: Array<Coder>): Array<any>;
|
||||
export declare class ArrayCoder extends Coder {
|
||||
readonly coder: Coder;
|
||||
readonly length: number;
|
||||
constructor(coder: Coder, length: number, localName: string);
|
||||
encode(writer: Writer, value: Array<any>): number;
|
||||
decode(reader: Reader): any;
|
||||
}
|
147
packages/abi/lib/coders/array.js
Normal file
147
packages/abi/lib/coders/array.js
Normal file
@ -0,0 +1,147 @@
|
||||
"use strict";
|
||||
var __extends = (this && this.__extends) || (function () {
|
||||
var extendStatics = function (d, b) {
|
||||
extendStatics = Object.setPrototypeOf ||
|
||||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
||||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
|
||||
return extendStatics(d, b);
|
||||
};
|
||||
return function (d, b) {
|
||||
extendStatics(d, b);
|
||||
function __() { this.constructor = d; }
|
||||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||||
};
|
||||
})();
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var logger_1 = require("@ethersproject/logger");
|
||||
var _version_1 = require("../_version");
|
||||
var logger = new logger_1.Logger(_version_1.version);
|
||||
var abstract_coder_1 = require("./abstract-coder");
|
||||
var anonymous_1 = require("./anonymous");
|
||||
function pack(writer, coders, values) {
|
||||
if (Array.isArray(values)) {
|
||||
// do nothing
|
||||
}
|
||||
else if (values && typeof (values) === "object") {
|
||||
var arrayValues_1 = [];
|
||||
coders.forEach(function (coder) {
|
||||
arrayValues_1.push(values[coder.localName]);
|
||||
});
|
||||
values = arrayValues_1;
|
||||
}
|
||||
else {
|
||||
logger.throwArgumentError("invalid tuple value", "tuple", values);
|
||||
}
|
||||
if (coders.length !== values.length) {
|
||||
logger.throwArgumentError("types/value length mismatch", "tuple", values);
|
||||
}
|
||||
var staticWriter = new abstract_coder_1.Writer(writer.wordSize);
|
||||
var dynamicWriter = new abstract_coder_1.Writer(writer.wordSize);
|
||||
var updateFuncs = [];
|
||||
coders.forEach(function (coder, index) {
|
||||
var value = values[index];
|
||||
if (coder.dynamic) {
|
||||
// Get current dynamic offset (for the future pointer)
|
||||
var dynamicOffset_1 = dynamicWriter.length;
|
||||
// Encode the dynamic value into the dynamicWriter
|
||||
coder.encode(dynamicWriter, value);
|
||||
// Prepare to populate the correct offset once we are done
|
||||
var updateFunc_1 = staticWriter.writeUpdatableValue();
|
||||
updateFuncs.push(function (baseOffset) {
|
||||
updateFunc_1(baseOffset + dynamicOffset_1);
|
||||
});
|
||||
}
|
||||
else {
|
||||
coder.encode(staticWriter, value);
|
||||
}
|
||||
});
|
||||
// Backfill all the dynamic offsets, now that we know the static length
|
||||
updateFuncs.forEach(function (func) { func(staticWriter.length); });
|
||||
var length = writer.writeBytes(staticWriter.data);
|
||||
length += writer.writeBytes(dynamicWriter.data);
|
||||
return length;
|
||||
}
|
||||
exports.pack = pack;
|
||||
function unpack(reader, coders) {
|
||||
var values = [];
|
||||
// A reader anchored to this base
|
||||
var baseReader = reader.subReader(0);
|
||||
// The amount of dynamic data read; to consume later to synchronize
|
||||
var dynamicLength = 0;
|
||||
coders.forEach(function (coder) {
|
||||
var value = null;
|
||||
if (coder.dynamic) {
|
||||
var offset = reader.readValue();
|
||||
var offsetReader = baseReader.subReader(offset.toNumber());
|
||||
value = coder.decode(offsetReader);
|
||||
dynamicLength += offsetReader.consumed;
|
||||
}
|
||||
else {
|
||||
value = coder.decode(reader);
|
||||
}
|
||||
if (value != undefined) {
|
||||
values.push(value);
|
||||
}
|
||||
});
|
||||
// @TODO: get rid of this an see if it still works?
|
||||
// Consume the dynamic components in the main reader
|
||||
reader.readBytes(dynamicLength);
|
||||
// Add any named parameters (i.e. tuples)
|
||||
coders.forEach(function (coder, index) {
|
||||
var name = coder.localName;
|
||||
if (!name) {
|
||||
return;
|
||||
}
|
||||
if (name === "length") {
|
||||
name = "_length";
|
||||
}
|
||||
if (values[name] != null) {
|
||||
return;
|
||||
}
|
||||
values[name] = values[index];
|
||||
});
|
||||
return values;
|
||||
}
|
||||
exports.unpack = unpack;
|
||||
var ArrayCoder = /** @class */ (function (_super) {
|
||||
__extends(ArrayCoder, _super);
|
||||
function ArrayCoder(coder, length, localName) {
|
||||
var _this = this;
|
||||
var type = (coder.type + "[" + (length >= 0 ? length : "") + "]");
|
||||
var dynamic = (length === -1 || coder.dynamic);
|
||||
_this = _super.call(this, "array", type, localName, dynamic) || this;
|
||||
_this.coder = coder;
|
||||
_this.length = length;
|
||||
return _this;
|
||||
}
|
||||
ArrayCoder.prototype.encode = function (writer, value) {
|
||||
if (!Array.isArray(value)) {
|
||||
this._throwError("expected array value", value);
|
||||
}
|
||||
var count = this.length;
|
||||
//let result = new Uint8Array(0);
|
||||
if (count === -1) {
|
||||
count = value.length;
|
||||
writer.writeValue(value.length);
|
||||
}
|
||||
logger.checkArgumentCount(count, value.length, "coder array" + (this.localName ? (" " + this.localName) : ""));
|
||||
var coders = [];
|
||||
for (var i = 0; i < value.length; i++) {
|
||||
coders.push(this.coder);
|
||||
}
|
||||
return pack(writer, coders, value);
|
||||
};
|
||||
ArrayCoder.prototype.decode = function (reader) {
|
||||
var count = this.length;
|
||||
if (count === -1) {
|
||||
count = reader.readValue().toNumber();
|
||||
}
|
||||
var coders = [];
|
||||
for (var i = 0; i < count; i++) {
|
||||
coders.push(new anonymous_1.AnonymousCoder(this.coder));
|
||||
}
|
||||
return reader.coerce(this.name, unpack(reader, coders));
|
||||
};
|
||||
return ArrayCoder;
|
||||
}(abstract_coder_1.Coder));
|
||||
exports.ArrayCoder = ArrayCoder;
|
6
packages/abi/lib/coders/boolean.d.ts
vendored
Normal file
6
packages/abi/lib/coders/boolean.d.ts
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
import { Coder, Reader, Writer } from "./abstract-coder";
|
||||
export declare class BooleanCoder extends Coder {
|
||||
constructor(localName: string);
|
||||
encode(writer: Writer, value: boolean): number;
|
||||
decode(reader: Reader): any;
|
||||
}
|
30
packages/abi/lib/coders/boolean.js
Normal file
30
packages/abi/lib/coders/boolean.js
Normal file
@ -0,0 +1,30 @@
|
||||
"use strict";
|
||||
var __extends = (this && this.__extends) || (function () {
|
||||
var extendStatics = function (d, b) {
|
||||
extendStatics = Object.setPrototypeOf ||
|
||||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
||||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
|
||||
return extendStatics(d, b);
|
||||
};
|
||||
return function (d, b) {
|
||||
extendStatics(d, b);
|
||||
function __() { this.constructor = d; }
|
||||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||||
};
|
||||
})();
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var abstract_coder_1 = require("./abstract-coder");
|
||||
var BooleanCoder = /** @class */ (function (_super) {
|
||||
__extends(BooleanCoder, _super);
|
||||
function BooleanCoder(localName) {
|
||||
return _super.call(this, "bool", "bool", localName, false) || this;
|
||||
}
|
||||
BooleanCoder.prototype.encode = function (writer, value) {
|
||||
return writer.writeValue(value ? 1 : 0);
|
||||
};
|
||||
BooleanCoder.prototype.decode = function (reader) {
|
||||
return reader.coerce(this.type, !reader.readValue().isZero());
|
||||
};
|
||||
return BooleanCoder;
|
||||
}(abstract_coder_1.Coder));
|
||||
exports.BooleanCoder = BooleanCoder;
|
10
packages/abi/lib/coders/bytes.d.ts
vendored
Normal file
10
packages/abi/lib/coders/bytes.d.ts
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
import { Coder, Reader, Writer } from "./abstract-coder";
|
||||
export declare class DynamicBytesCoder extends Coder {
|
||||
constructor(type: string, localName: string);
|
||||
encode(writer: Writer, value: any): number;
|
||||
decode(reader: Reader): any;
|
||||
}
|
||||
export declare class BytesCoder extends DynamicBytesCoder {
|
||||
constructor(localName: string);
|
||||
decode(reader: Reader): any;
|
||||
}
|
45
packages/abi/lib/coders/bytes.js
Normal file
45
packages/abi/lib/coders/bytes.js
Normal file
@ -0,0 +1,45 @@
|
||||
"use strict";
|
||||
var __extends = (this && this.__extends) || (function () {
|
||||
var extendStatics = function (d, b) {
|
||||
extendStatics = Object.setPrototypeOf ||
|
||||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
||||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
|
||||
return extendStatics(d, b);
|
||||
};
|
||||
return function (d, b) {
|
||||
extendStatics(d, b);
|
||||
function __() { this.constructor = d; }
|
||||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||||
};
|
||||
})();
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var bytes_1 = require("@ethersproject/bytes");
|
||||
var abstract_coder_1 = require("./abstract-coder");
|
||||
var DynamicBytesCoder = /** @class */ (function (_super) {
|
||||
__extends(DynamicBytesCoder, _super);
|
||||
function DynamicBytesCoder(type, localName) {
|
||||
return _super.call(this, type, type, localName, true) || this;
|
||||
}
|
||||
DynamicBytesCoder.prototype.encode = function (writer, value) {
|
||||
value = bytes_1.arrayify(value);
|
||||
var length = writer.writeValue(value.length);
|
||||
length += writer.writeBytes(value);
|
||||
return length;
|
||||
};
|
||||
DynamicBytesCoder.prototype.decode = function (reader) {
|
||||
return reader.readBytes(reader.readValue().toNumber());
|
||||
};
|
||||
return DynamicBytesCoder;
|
||||
}(abstract_coder_1.Coder));
|
||||
exports.DynamicBytesCoder = DynamicBytesCoder;
|
||||
var BytesCoder = /** @class */ (function (_super) {
|
||||
__extends(BytesCoder, _super);
|
||||
function BytesCoder(localName) {
|
||||
return _super.call(this, "bytes", localName) || this;
|
||||
}
|
||||
BytesCoder.prototype.decode = function (reader) {
|
||||
return reader.coerce(this.name, bytes_1.hexlify(_super.prototype.decode.call(this, reader)));
|
||||
};
|
||||
return BytesCoder;
|
||||
}(DynamicBytesCoder));
|
||||
exports.BytesCoder = BytesCoder;
|
8
packages/abi/lib/coders/fixed-bytes.d.ts
vendored
Normal file
8
packages/abi/lib/coders/fixed-bytes.d.ts
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
import { BytesLike } from "@ethersproject/bytes";
|
||||
import { Coder, Reader, Writer } from "./abstract-coder";
|
||||
export declare class FixedBytesCoder extends Coder {
|
||||
readonly size: number;
|
||||
constructor(size: number, localName: string);
|
||||
encode(writer: Writer, value: BytesLike): number;
|
||||
decode(reader: Reader): any;
|
||||
}
|
40
packages/abi/lib/coders/fixed-bytes.js
Normal file
40
packages/abi/lib/coders/fixed-bytes.js
Normal file
@ -0,0 +1,40 @@
|
||||
"use strict";
|
||||
var __extends = (this && this.__extends) || (function () {
|
||||
var extendStatics = function (d, b) {
|
||||
extendStatics = Object.setPrototypeOf ||
|
||||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
||||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
|
||||
return extendStatics(d, b);
|
||||
};
|
||||
return function (d, b) {
|
||||
extendStatics(d, b);
|
||||
function __() { this.constructor = d; }
|
||||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||||
};
|
||||
})();
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var bytes_1 = require("@ethersproject/bytes");
|
||||
var abstract_coder_1 = require("./abstract-coder");
|
||||
// @TODO: Merge this with bytes
|
||||
var FixedBytesCoder = /** @class */ (function (_super) {
|
||||
__extends(FixedBytesCoder, _super);
|
||||
function FixedBytesCoder(size, localName) {
|
||||
var _this = this;
|
||||
var name = "bytes" + String(size);
|
||||
_this = _super.call(this, name, name, localName, false) || this;
|
||||
_this.size = size;
|
||||
return _this;
|
||||
}
|
||||
FixedBytesCoder.prototype.encode = function (writer, value) {
|
||||
var data = bytes_1.arrayify(value);
|
||||
if (data.length !== this.size) {
|
||||
this._throwError("incorrect data length", value);
|
||||
}
|
||||
return writer.writeBytes(data);
|
||||
};
|
||||
FixedBytesCoder.prototype.decode = function (reader) {
|
||||
return reader.coerce(this.name, bytes_1.hexlify(reader.readBytes(this.size)));
|
||||
};
|
||||
return FixedBytesCoder;
|
||||
}(abstract_coder_1.Coder));
|
||||
exports.FixedBytesCoder = FixedBytesCoder;
|
6
packages/abi/lib/coders/null.d.ts
vendored
Normal file
6
packages/abi/lib/coders/null.d.ts
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
import { Coder, Reader, Writer } from "./abstract-coder";
|
||||
export declare class NullCoder extends Coder {
|
||||
constructor(localName: string);
|
||||
encode(writer: Writer, value: any): number;
|
||||
decode(reader: Reader): any;
|
||||
}
|
34
packages/abi/lib/coders/null.js
Normal file
34
packages/abi/lib/coders/null.js
Normal file
@ -0,0 +1,34 @@
|
||||
"use strict";
|
||||
var __extends = (this && this.__extends) || (function () {
|
||||
var extendStatics = function (d, b) {
|
||||
extendStatics = Object.setPrototypeOf ||
|
||||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
||||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
|
||||
return extendStatics(d, b);
|
||||
};
|
||||
return function (d, b) {
|
||||
extendStatics(d, b);
|
||||
function __() { this.constructor = d; }
|
||||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||||
};
|
||||
})();
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var abstract_coder_1 = require("./abstract-coder");
|
||||
var NullCoder = /** @class */ (function (_super) {
|
||||
__extends(NullCoder, _super);
|
||||
function NullCoder(localName) {
|
||||
return _super.call(this, "null", "", localName, false) || this;
|
||||
}
|
||||
NullCoder.prototype.encode = function (writer, value) {
|
||||
if (value != null) {
|
||||
this._throwError("not null", value);
|
||||
}
|
||||
return writer.writeBytes([]);
|
||||
};
|
||||
NullCoder.prototype.decode = function (reader) {
|
||||
reader.readBytes(0);
|
||||
return reader.coerce(this.name, null);
|
||||
};
|
||||
return NullCoder;
|
||||
}(abstract_coder_1.Coder));
|
||||
exports.NullCoder = NullCoder;
|
9
packages/abi/lib/coders/number.d.ts
vendored
Normal file
9
packages/abi/lib/coders/number.d.ts
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
import { BigNumberish } from "@ethersproject/bignumber";
|
||||
import { Coder, Reader, Writer } from "./abstract-coder";
|
||||
export declare class NumberCoder extends Coder {
|
||||
readonly size: number;
|
||||
readonly signed: boolean;
|
||||
constructor(size: number, signed: boolean, localName: string);
|
||||
encode(writer: Writer, value: BigNumberish): number;
|
||||
decode(reader: Reader): any;
|
||||
}
|
57
packages/abi/lib/coders/number.js
Normal file
57
packages/abi/lib/coders/number.js
Normal file
@ -0,0 +1,57 @@
|
||||
"use strict";
|
||||
var __extends = (this && this.__extends) || (function () {
|
||||
var extendStatics = function (d, b) {
|
||||
extendStatics = Object.setPrototypeOf ||
|
||||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
||||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
|
||||
return extendStatics(d, b);
|
||||
};
|
||||
return function (d, b) {
|
||||
extendStatics(d, b);
|
||||
function __() { this.constructor = d; }
|
||||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||||
};
|
||||
})();
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var bignumber_1 = require("@ethersproject/bignumber");
|
||||
var constants_1 = require("@ethersproject/constants");
|
||||
var abstract_coder_1 = require("./abstract-coder");
|
||||
var NumberCoder = /** @class */ (function (_super) {
|
||||
__extends(NumberCoder, _super);
|
||||
function NumberCoder(size, signed, localName) {
|
||||
var _this = this;
|
||||
var name = ((signed ? "int" : "uint") + (size * 8));
|
||||
_this = _super.call(this, name, name, localName, false) || this;
|
||||
_this.size = size;
|
||||
_this.signed = signed;
|
||||
return _this;
|
||||
}
|
||||
NumberCoder.prototype.encode = function (writer, value) {
|
||||
var v = bignumber_1.BigNumber.from(value);
|
||||
// Check bounds are safe for encoding
|
||||
var maxUintValue = constants_1.MaxUint256.maskn(writer.wordSize * 8);
|
||||
if (this.signed) {
|
||||
var bounds = maxUintValue.maskn(this.size * 8 - 1);
|
||||
if (v.gt(bounds) || v.lt(bounds.add(constants_1.One).mul(constants_1.NegativeOne))) {
|
||||
this._throwError("value out-of-bounds", value);
|
||||
}
|
||||
}
|
||||
else if (v.lt(constants_1.Zero) || v.gt(maxUintValue.maskn(this.size * 8))) {
|
||||
this._throwError("value out-of-bounds", value);
|
||||
}
|
||||
v = v.toTwos(this.size * 8).maskn(this.size * 8);
|
||||
if (this.signed) {
|
||||
v = v.fromTwos(this.size * 8).toTwos(8 * writer.wordSize);
|
||||
}
|
||||
return writer.writeValue(v);
|
||||
};
|
||||
NumberCoder.prototype.decode = function (reader) {
|
||||
var value = reader.readValue().maskn(this.size * 8);
|
||||
if (this.signed) {
|
||||
value = value.fromTwos(this.size * 8);
|
||||
}
|
||||
return reader.coerce(this.name, value);
|
||||
};
|
||||
return NumberCoder;
|
||||
}(abstract_coder_1.Coder));
|
||||
exports.NumberCoder = NumberCoder;
|
7
packages/abi/lib/coders/string.d.ts
vendored
Normal file
7
packages/abi/lib/coders/string.d.ts
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
import { Reader, Writer } from "./abstract-coder";
|
||||
import { DynamicBytesCoder } from "./bytes";
|
||||
export declare class StringCoder extends DynamicBytesCoder {
|
||||
constructor(localName: string);
|
||||
encode(writer: Writer, value: any): number;
|
||||
decode(reader: Reader): any;
|
||||
}
|
31
packages/abi/lib/coders/string.js
Normal file
31
packages/abi/lib/coders/string.js
Normal file
@ -0,0 +1,31 @@
|
||||
"use strict";
|
||||
var __extends = (this && this.__extends) || (function () {
|
||||
var extendStatics = function (d, b) {
|
||||
extendStatics = Object.setPrototypeOf ||
|
||||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
||||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
|
||||
return extendStatics(d, b);
|
||||
};
|
||||
return function (d, b) {
|
||||
extendStatics(d, b);
|
||||
function __() { this.constructor = d; }
|
||||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||||
};
|
||||
})();
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var strings_1 = require("@ethersproject/strings");
|
||||
var bytes_1 = require("./bytes");
|
||||
var StringCoder = /** @class */ (function (_super) {
|
||||
__extends(StringCoder, _super);
|
||||
function StringCoder(localName) {
|
||||
return _super.call(this, "string", localName) || this;
|
||||
}
|
||||
StringCoder.prototype.encode = function (writer, value) {
|
||||
return _super.prototype.encode.call(this, writer, strings_1.toUtf8Bytes(value));
|
||||
};
|
||||
StringCoder.prototype.decode = function (reader) {
|
||||
return strings_1.toUtf8String(_super.prototype.decode.call(this, reader));
|
||||
};
|
||||
return StringCoder;
|
||||
}(bytes_1.DynamicBytesCoder));
|
||||
exports.StringCoder = StringCoder;
|
7
packages/abi/lib/coders/tuple.d.ts
vendored
Normal file
7
packages/abi/lib/coders/tuple.d.ts
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
import { Coder, Reader, Writer } from "./abstract-coder";
|
||||
export declare class TupleCoder extends Coder {
|
||||
readonly coders: Array<Coder>;
|
||||
constructor(coders: Array<Coder>, localName: string);
|
||||
encode(writer: Writer, value: Array<any>): number;
|
||||
decode(reader: Reader): any;
|
||||
}
|
43
packages/abi/lib/coders/tuple.js
Normal file
43
packages/abi/lib/coders/tuple.js
Normal file
@ -0,0 +1,43 @@
|
||||
"use strict";
|
||||
var __extends = (this && this.__extends) || (function () {
|
||||
var extendStatics = function (d, b) {
|
||||
extendStatics = Object.setPrototypeOf ||
|
||||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
||||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
|
||||
return extendStatics(d, b);
|
||||
};
|
||||
return function (d, b) {
|
||||
extendStatics(d, b);
|
||||
function __() { this.constructor = d; }
|
||||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||||
};
|
||||
})();
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var abstract_coder_1 = require("./abstract-coder");
|
||||
var array_1 = require("./array");
|
||||
var TupleCoder = /** @class */ (function (_super) {
|
||||
__extends(TupleCoder, _super);
|
||||
function TupleCoder(coders, localName) {
|
||||
var _this = this;
|
||||
var dynamic = false;
|
||||
var types = [];
|
||||
coders.forEach(function (coder) {
|
||||
if (coder.dynamic) {
|
||||
dynamic = true;
|
||||
}
|
||||
types.push(coder.type);
|
||||
});
|
||||
var type = ("tuple(" + types.join(",") + ")");
|
||||
_this = _super.call(this, "tuple", type, localName, dynamic) || this;
|
||||
_this.coders = coders;
|
||||
return _this;
|
||||
}
|
||||
TupleCoder.prototype.encode = function (writer, value) {
|
||||
return array_1.pack(writer, this.coders, value);
|
||||
};
|
||||
TupleCoder.prototype.decode = function (reader) {
|
||||
return reader.coerce(this.name, array_1.unpack(reader, this.coders));
|
||||
};
|
||||
return TupleCoder;
|
||||
}(abstract_coder_1.Coder));
|
||||
exports.TupleCoder = TupleCoder;
|
76
packages/abi/lib/fragments.d.ts
vendored
Normal file
76
packages/abi/lib/fragments.d.ts
vendored
Normal file
@ -0,0 +1,76 @@
|
||||
import { BigNumber } from "@ethersproject/bignumber";
|
||||
export interface JsonFragmentType {
|
||||
name?: string;
|
||||
indexed?: boolean;
|
||||
type?: string;
|
||||
components?: Array<JsonFragmentType>;
|
||||
}
|
||||
export interface JsonFragment {
|
||||
name?: string;
|
||||
type?: string;
|
||||
anonymous?: boolean;
|
||||
payable?: boolean;
|
||||
constant?: boolean;
|
||||
stateMutability?: string;
|
||||
inputs?: Array<JsonFragmentType>;
|
||||
outputs?: Array<JsonFragmentType>;
|
||||
gas?: string;
|
||||
}
|
||||
export declare const FormatTypes: {
|
||||
[name: string]: string;
|
||||
};
|
||||
export declare class ParamType {
|
||||
readonly name: string;
|
||||
readonly type: string;
|
||||
readonly baseType: string;
|
||||
readonly indexed: boolean;
|
||||
readonly components: Array<ParamType>;
|
||||
readonly arrayLength: number;
|
||||
readonly arrayChildren: ParamType;
|
||||
readonly _isParamType: boolean;
|
||||
constructor(constructorGuard: any, params: any);
|
||||
format(format?: string): string;
|
||||
static from(value: string | JsonFragmentType | ParamType, allowIndexed?: boolean): ParamType;
|
||||
static fromObject(value: JsonFragmentType | ParamType): ParamType;
|
||||
static fromString(value: string, allowIndexed?: boolean): ParamType;
|
||||
static isParamType(value: any): value is ParamType;
|
||||
}
|
||||
export declare abstract class Fragment {
|
||||
readonly type: string;
|
||||
readonly name: string;
|
||||
readonly inputs: Array<ParamType>;
|
||||
readonly _isFragment: boolean;
|
||||
constructor(constructorGuard: any, params: any);
|
||||
abstract format(format?: string): string;
|
||||
static from(value: Fragment | JsonFragment | string): Fragment;
|
||||
static fromObject(value: Fragment | JsonFragment): Fragment;
|
||||
static fromString(value: string): Fragment;
|
||||
static isFragment(value: any): value is Fragment;
|
||||
}
|
||||
export declare class EventFragment extends Fragment {
|
||||
readonly anonymous: boolean;
|
||||
format(format?: string): string;
|
||||
static from(value: EventFragment | JsonFragment | string): EventFragment;
|
||||
static fromObject(value: JsonFragment | EventFragment): EventFragment;
|
||||
static fromString(value: string): EventFragment;
|
||||
static isEventFragment(value: any): value is EventFragment;
|
||||
}
|
||||
export declare class ConstructorFragment extends Fragment {
|
||||
stateMutability: string;
|
||||
payable: boolean;
|
||||
gas?: BigNumber;
|
||||
format(format?: string): string;
|
||||
static from(value: ConstructorFragment | JsonFragment | string): ConstructorFragment;
|
||||
static fromObject(value: ConstructorFragment | JsonFragment): ConstructorFragment;
|
||||
static fromString(value: string): ConstructorFragment;
|
||||
static isConstructorFragment(value: any): value is ConstructorFragment;
|
||||
}
|
||||
export declare class FunctionFragment extends ConstructorFragment {
|
||||
constant: boolean;
|
||||
outputs?: Array<ParamType>;
|
||||
format(format?: string): string;
|
||||
static from(value: FunctionFragment | JsonFragment | string): FunctionFragment;
|
||||
static fromObject(value: FunctionFragment | JsonFragment): FunctionFragment;
|
||||
static fromString(value: string): FunctionFragment;
|
||||
static isFunctionFragment(value: any): value is FunctionFragment;
|
||||
}
|
4
packages/abi/lib/index.d.ts
vendored
Normal file
4
packages/abi/lib/index.d.ts
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
import { ConstructorFragment, EventFragment, FormatTypes, Fragment, FunctionFragment, JsonFragment, JsonFragmentType, ParamType } from "./fragments";
|
||||
import { AbiCoder, CoerceFunc, defaultAbiCoder } from "./abi-coder";
|
||||
import { Indexed, Interface } from "./interface";
|
||||
export { ConstructorFragment, EventFragment, Fragment, FunctionFragment, ParamType, FormatTypes, AbiCoder, defaultAbiCoder, Interface, Indexed, CoerceFunc, JsonFragment, JsonFragmentType };
|
70
packages/abi/lib/interface.d.ts
vendored
Normal file
70
packages/abi/lib/interface.d.ts
vendored
Normal file
@ -0,0 +1,70 @@
|
||||
import { BigNumber, BigNumberish } from "@ethersproject/bignumber";
|
||||
import { BytesLike } from "@ethersproject/bytes";
|
||||
import { Description } from "@ethersproject/properties";
|
||||
import { AbiCoder } from "./abi-coder";
|
||||
import { ConstructorFragment, EventFragment, Fragment, FunctionFragment, JsonFragment, ParamType } from "./fragments";
|
||||
export declare class LogDescription extends Description {
|
||||
readonly eventFragment: EventFragment;
|
||||
readonly name: string;
|
||||
readonly signature: string;
|
||||
readonly topic: string;
|
||||
readonly values: any;
|
||||
}
|
||||
export declare class TransactionDescription extends Description {
|
||||
readonly functionFragment: FunctionFragment;
|
||||
readonly name: string;
|
||||
readonly args: Array<any>;
|
||||
readonly signature: string;
|
||||
readonly sighash: string;
|
||||
readonly value: BigNumber;
|
||||
}
|
||||
export declare class Indexed extends Description {
|
||||
readonly hash: string;
|
||||
static isIndexed(value: any): value is Indexed;
|
||||
}
|
||||
export declare class Result {
|
||||
[key: string]: any;
|
||||
[key: number]: any;
|
||||
}
|
||||
export declare class Interface {
|
||||
readonly fragments: Array<Fragment>;
|
||||
readonly errors: {
|
||||
[name: string]: any;
|
||||
};
|
||||
readonly events: {
|
||||
[name: string]: EventFragment;
|
||||
};
|
||||
readonly functions: {
|
||||
[name: string]: FunctionFragment;
|
||||
};
|
||||
readonly structs: {
|
||||
[name: string]: any;
|
||||
};
|
||||
readonly deploy: ConstructorFragment;
|
||||
readonly _abiCoder: AbiCoder;
|
||||
static _isInterface: boolean;
|
||||
constructor(fragments: string | Array<Fragment | JsonFragment | string>);
|
||||
static getAbiCoder(): AbiCoder;
|
||||
static getAddress(address: string): string;
|
||||
_sighashify(functionFragment: FunctionFragment): string;
|
||||
_topicify(eventFragment: EventFragment): string;
|
||||
getFunction(nameOrSignatureOrSighash: string): FunctionFragment;
|
||||
getEvent(nameOrSignatureOrTopic: string): EventFragment;
|
||||
getSighash(functionFragment: FunctionFragment | string): string;
|
||||
getEventTopic(eventFragment: EventFragment | string): string;
|
||||
_encodeParams(params: Array<ParamType>, values: Array<any>): string;
|
||||
encodeDeploy(values?: Array<any>): string;
|
||||
encodeFunctionData(functionFragment: FunctionFragment | string, values?: Array<any>): string;
|
||||
decodeFunctionResult(functionFragment: FunctionFragment | string, data: BytesLike): Array<any>;
|
||||
encodeFilterTopics(eventFragment: EventFragment, values: Array<any>): Array<string | Array<string>>;
|
||||
decodeEventLog(eventFragment: EventFragment | string, data: BytesLike, topics?: Array<string>): Array<any>;
|
||||
parseTransaction(tx: {
|
||||
data: string;
|
||||
value?: BigNumberish;
|
||||
}): TransactionDescription;
|
||||
parseLog(log: {
|
||||
topics: Array<string>;
|
||||
data: string;
|
||||
}): LogDescription;
|
||||
static isInterface(value: any): value is Interface;
|
||||
}
|
@ -1,21 +1,21 @@
|
||||
{
|
||||
"name": "@ethersproject/abi",
|
||||
"version": "5.0.0-beta.136",
|
||||
"version": "5.0.0-beta.137",
|
||||
"description": "Utilities and Classes for parsing, formatting and managing Ethereum ABIs.",
|
||||
"main": "index.js",
|
||||
"main": "./lib/index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ethersproject/address": ">5.0.0-beta.0",
|
||||
"@ethersproject/bignumber": ">5.0.0-beta.0",
|
||||
"@ethersproject/bytes": ">5.0.0-beta.0",
|
||||
"@ethersproject/constants": ">5.0.0-beta.0",
|
||||
"@ethersproject/hash": ">5.0.0-beta.0",
|
||||
"@ethersproject/keccak256": ">5.0.0-beta.0",
|
||||
"@ethersproject/logger": ">5.0.0-beta.0",
|
||||
"@ethersproject/properties": ">5.0.0-beta.0",
|
||||
"@ethersproject/strings": ">5.0.0-beta.0"
|
||||
"@ethersproject/address": ">=5.0.0-beta.128",
|
||||
"@ethersproject/bignumber": ">=5.0.0-beta.130",
|
||||
"@ethersproject/bytes": ">=5.0.0-beta.129",
|
||||
"@ethersproject/constants": ">=5.0.0-beta.128",
|
||||
"@ethersproject/hash": ">=5.0.0-beta.128",
|
||||
"@ethersproject/keccak256": ">=5.0.0-beta.127",
|
||||
"@ethersproject/logger": ">=5.0.0-beta.129",
|
||||
"@ethersproject/properties": ">=5.0.0-beta.131",
|
||||
"@ethersproject/strings": ">=5.0.0-beta.130"
|
||||
},
|
||||
"keywords": [
|
||||
"Ethereum",
|
||||
@ -30,5 +30,7 @@
|
||||
"type": "git",
|
||||
"url": "git://github.com/ethers-io/ethers.js.git"
|
||||
},
|
||||
"tarballHash": "0x9585dafdf431d8f83f4eb02869142a31ef6dfec6638c5706517d012eb363ad47"
|
||||
"module": "./lib.esm/index.js",
|
||||
"types": "./lib/index.d.ts",
|
||||
"tarballHash": "0x2586b6ca7027e4b47caf53887eae7d3aca64570fb72bcb495838b883be6580f3"
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
"use trict";
|
||||
"use strict";
|
||||
|
||||
import { arrayify, BytesLike, concat, hexlify } from "@ethersproject/bytes";
|
||||
import { BigNumber, BigNumberish } from "@ethersproject/bignumber";
|
||||
|
@ -1,4 +0,0 @@
|
||||
let { defaultAbiCoder } = require(".");
|
||||
|
||||
console.log(defaultAbiCoder);
|
||||
console.log(defaultAbiCoder.encode([ "uint256", "bytes" ], [ 42, "0x1234" ]));
|
@ -2,12 +2,11 @@
|
||||
"extends": "../../tsconfig.package.json",
|
||||
"compilerOptions": {
|
||||
"rootDir": "./src.ts",
|
||||
"outDir": "./"
|
||||
"outDir": "./lib/"
|
||||
},
|
||||
"include": [
|
||||
"./src.ts/*.ts",
|
||||
"./src.ts/coders/*.ts"
|
||||
"./src.ts/*.ts",
|
||||
"./src.ts/coders/*.ts"
|
||||
],
|
||||
"exclude": [ ]
|
||||
"exclude": []
|
||||
}
|
||||
|
||||
|
0
packages/abstract-provider/_version.d.ts → packages/abstract-provider/lib.esm/_version.d.ts
vendored
0
packages/abstract-provider/_version.d.ts → packages/abstract-provider/lib.esm/_version.d.ts
vendored
1
packages/abstract-provider/lib.esm/_version.js
Normal file
1
packages/abstract-provider/lib.esm/_version.js
Normal file
@ -0,0 +1 @@
|
||||
export const version = "abstract-provider/5.0.0-beta.130";
|
78
packages/abstract-provider/lib.esm/index.js
Normal file
78
packages/abstract-provider/lib.esm/index.js
Normal file
@ -0,0 +1,78 @@
|
||||
"use strict";
|
||||
import { isHexString } from "@ethersproject/bytes";
|
||||
import { Description, defineReadOnly } from "@ethersproject/properties";
|
||||
import { Logger } from "@ethersproject/logger";
|
||||
import { version } from "./_version";
|
||||
const logger = new Logger(version);
|
||||
;
|
||||
;
|
||||
//export type CallTransactionable = {
|
||||
// call(transaction: TransactionRequest): Promise<TransactionResponse>;
|
||||
//};
|
||||
export class ForkEvent extends Description {
|
||||
static isForkEvent(value) {
|
||||
return !!(value && value._isForkEvent);
|
||||
}
|
||||
}
|
||||
export class BlockForkEvent extends ForkEvent {
|
||||
constructor(blockhash, expiry) {
|
||||
if (!isHexString(blockhash, 32)) {
|
||||
logger.throwArgumentError("invalid blockhash", "blockhash", blockhash);
|
||||
}
|
||||
super({
|
||||
_isForkEvent: true,
|
||||
_isBlockForkEvent: true,
|
||||
expiry: (expiry || 0),
|
||||
blockHash: blockhash
|
||||
});
|
||||
}
|
||||
}
|
||||
export class TransactionForkEvent extends ForkEvent {
|
||||
constructor(hash, expiry) {
|
||||
if (!isHexString(hash, 32)) {
|
||||
logger.throwArgumentError("invalid transaction hash", "hash", hash);
|
||||
}
|
||||
super({
|
||||
_isForkEvent: true,
|
||||
_isTransactionForkEvent: true,
|
||||
expiry: (expiry || 0),
|
||||
hash: hash
|
||||
});
|
||||
}
|
||||
}
|
||||
export class TransactionOrderForkEvent extends ForkEvent {
|
||||
constructor(beforeHash, afterHash, expiry) {
|
||||
if (!isHexString(beforeHash, 32)) {
|
||||
logger.throwArgumentError("invalid transaction hash", "beforeHash", beforeHash);
|
||||
}
|
||||
if (!isHexString(afterHash, 32)) {
|
||||
logger.throwArgumentError("invalid transaction hash", "afterHash", afterHash);
|
||||
}
|
||||
super({
|
||||
_isForkEvent: true,
|
||||
_isTransactionOrderForkEvent: true,
|
||||
expiry: (expiry || 0),
|
||||
beforeHash: beforeHash,
|
||||
afterHash: afterHash
|
||||
});
|
||||
}
|
||||
}
|
||||
///////////////////////////////
|
||||
// Exported Abstracts
|
||||
export class Provider {
|
||||
constructor() {
|
||||
logger.checkAbstract(new.target, Provider);
|
||||
defineReadOnly(this, "_isProvider", true);
|
||||
}
|
||||
// Alias for "on"
|
||||
addListener(eventName, listener) {
|
||||
return this.on(eventName, listener);
|
||||
}
|
||||
// Alias for "off"
|
||||
removeListener(eventName, listener) {
|
||||
return this.off(eventName, listener);
|
||||
}
|
||||
static isProvider(value) {
|
||||
return !!(value && value._isProvider);
|
||||
}
|
||||
}
|
1
packages/abstract-provider/lib/_version.d.ts
vendored
Normal file
1
packages/abstract-provider/lib/_version.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
||||
export declare const version = "abstract-provider/5.0.0-beta.130";
|
138
packages/abstract-provider/lib/index.d.ts
vendored
Normal file
138
packages/abstract-provider/lib/index.d.ts
vendored
Normal file
@ -0,0 +1,138 @@
|
||||
import { BigNumber, BigNumberish } from "@ethersproject/bignumber";
|
||||
import { BytesLike } from "@ethersproject/bytes";
|
||||
import { Network } from "@ethersproject/networks";
|
||||
import { Description } from "@ethersproject/properties";
|
||||
import { Transaction } from "@ethersproject/transactions";
|
||||
import { OnceBlockable } from "@ethersproject/web";
|
||||
export declare type TransactionRequest = {
|
||||
to?: string | Promise<string>;
|
||||
from?: string | Promise<string>;
|
||||
nonce?: BigNumberish | Promise<BigNumberish>;
|
||||
gasLimit?: BigNumberish | Promise<BigNumberish>;
|
||||
gasPrice?: BigNumberish | Promise<BigNumberish>;
|
||||
data?: BytesLike | Promise<BytesLike>;
|
||||
value?: BigNumberish | Promise<BigNumberish>;
|
||||
chainId?: number | Promise<number>;
|
||||
};
|
||||
export interface TransactionResponse extends Transaction {
|
||||
hash: string;
|
||||
blockNumber?: number;
|
||||
blockHash?: string;
|
||||
timestamp?: number;
|
||||
confirmations: number;
|
||||
from: string;
|
||||
raw?: string;
|
||||
wait: (confirmations?: number) => Promise<TransactionReceipt>;
|
||||
}
|
||||
export declare type BlockTag = string | number;
|
||||
interface _Block {
|
||||
hash: string;
|
||||
parentHash: string;
|
||||
number: number;
|
||||
timestamp: number;
|
||||
nonce: string;
|
||||
difficulty: number;
|
||||
gasLimit: BigNumber;
|
||||
gasUsed: BigNumber;
|
||||
miner: string;
|
||||
extraData: string;
|
||||
}
|
||||
export interface Block extends _Block {
|
||||
transactions: Array<string>;
|
||||
}
|
||||
export interface BlockWithTransactions extends _Block {
|
||||
transactions: Array<TransactionResponse>;
|
||||
}
|
||||
export interface Log {
|
||||
blockNumber?: number;
|
||||
blockHash?: string;
|
||||
transactionIndex?: number;
|
||||
removed?: boolean;
|
||||
transactionLogIndex?: number;
|
||||
address: string;
|
||||
data: string;
|
||||
topics: Array<string>;
|
||||
transactionHash?: string;
|
||||
logIndex?: number;
|
||||
}
|
||||
export interface TransactionReceipt {
|
||||
to?: string;
|
||||
from?: string;
|
||||
contractAddress?: string;
|
||||
transactionIndex?: number;
|
||||
root?: string;
|
||||
gasUsed?: BigNumber;
|
||||
logsBloom?: string;
|
||||
blockHash?: string;
|
||||
transactionHash?: string;
|
||||
logs?: Array<Log>;
|
||||
blockNumber?: number;
|
||||
confirmations?: number;
|
||||
cumulativeGasUsed?: BigNumber;
|
||||
byzantium: boolean;
|
||||
status?: number;
|
||||
}
|
||||
export interface EventFilter {
|
||||
address?: string;
|
||||
topics?: Array<string | Array<string>>;
|
||||
}
|
||||
export interface Filter extends EventFilter {
|
||||
fromBlock?: BlockTag;
|
||||
toBlock?: BlockTag;
|
||||
}
|
||||
export interface FilterByBlockHash extends EventFilter {
|
||||
blockhash?: string;
|
||||
}
|
||||
export declare abstract class ForkEvent extends Description {
|
||||
readonly expiry: number;
|
||||
readonly _isForkEvent: boolean;
|
||||
static isForkEvent(value: any): value is ForkEvent;
|
||||
}
|
||||
export declare class BlockForkEvent extends ForkEvent {
|
||||
readonly blockhash: string;
|
||||
constructor(blockhash: string, expiry?: number);
|
||||
}
|
||||
export declare class TransactionForkEvent extends ForkEvent {
|
||||
readonly hash: string;
|
||||
constructor(hash: string, expiry?: number);
|
||||
}
|
||||
export declare class TransactionOrderForkEvent extends ForkEvent {
|
||||
readonly beforeHash: string;
|
||||
readonly afterHash: string;
|
||||
constructor(beforeHash: string, afterHash: string, expiry?: number);
|
||||
}
|
||||
export declare type EventType = string | Array<string | Array<string>> | EventFilter | ForkEvent;
|
||||
export declare type Listener = (...args: Array<any>) => void;
|
||||
export declare abstract class Provider implements OnceBlockable {
|
||||
abstract getNetwork(): Promise<Network>;
|
||||
abstract getBlockNumber(): Promise<number>;
|
||||
abstract getGasPrice(): Promise<BigNumber>;
|
||||
abstract getBalance(addressOrName: string | Promise<string>, blockTag?: BlockTag | Promise<BlockTag>): Promise<BigNumber>;
|
||||
abstract getTransactionCount(addressOrName: string | Promise<string>, blockTag?: BlockTag | Promise<BlockTag>): Promise<number>;
|
||||
abstract getCode(addressOrName: string | Promise<string>, blockTag?: BlockTag | Promise<BlockTag>): Promise<string>;
|
||||
abstract getStorageAt(addressOrName: string | Promise<string>, position: BigNumberish | Promise<BigNumberish>, blockTag?: BlockTag | Promise<BlockTag>): Promise<string>;
|
||||
abstract sendTransaction(signedTransaction: string | Promise<string>): Promise<TransactionResponse>;
|
||||
abstract call(transaction: TransactionRequest, blockTag?: BlockTag | Promise<BlockTag>): Promise<string>;
|
||||
abstract estimateGas(transaction: TransactionRequest): Promise<BigNumber>;
|
||||
abstract getBlock(blockHashOrBlockTag: BlockTag | string | Promise<BlockTag | string>): Promise<Block>;
|
||||
abstract getBlockWithTransactions(blockHashOrBlockTag: BlockTag | string | Promise<BlockTag | string>): Promise<BlockWithTransactions>;
|
||||
abstract getTransaction(transactionHash: string): Promise<TransactionResponse>;
|
||||
abstract getTransactionReceipt(transactionHash: string): Promise<TransactionReceipt>;
|
||||
abstract getLogs(filter: Filter): Promise<Array<Log>>;
|
||||
abstract resolveName(name: string | Promise<string>): Promise<string>;
|
||||
abstract lookupAddress(address: string | Promise<string>): Promise<string>;
|
||||
abstract on(eventName: EventType, listener: Listener): Provider;
|
||||
abstract once(eventName: EventType, listener: Listener): Provider;
|
||||
abstract emit(eventName: EventType, ...args: Array<any>): boolean;
|
||||
abstract listenerCount(eventName?: EventType): number;
|
||||
abstract listeners(eventName?: EventType): Array<Listener>;
|
||||
abstract off(eventName: EventType, listener?: Listener): Provider;
|
||||
abstract removeAllListeners(eventName?: EventType): Provider;
|
||||
addListener(eventName: EventType, listener: Listener): Provider;
|
||||
removeListener(eventName: EventType, listener: Listener): Provider;
|
||||
abstract waitForTransaction(transactionHash: string, timeout?: number): Promise<TransactionReceipt>;
|
||||
readonly _isProvider: boolean;
|
||||
constructor();
|
||||
static isProvider(value: any): value is Provider;
|
||||
}
|
||||
export {};
|
@ -1,23 +1,19 @@
|
||||
{
|
||||
"name": "@ethersproject/abstract-provider",
|
||||
"version": "5.0.0-beta.130",
|
||||
"version": "5.0.0-beta.131",
|
||||
"description": "An Abstract Class for describing an Ethereum Provider for ethers.",
|
||||
"main": "index.js",
|
||||
"browser": {
|
||||
"net": "./browser-net.js",
|
||||
"./ipc-provider": "./browser-ipc-provider"
|
||||
},
|
||||
"main": "./lib/index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ethersproject/bignumber": ">5.0.0-beta.0",
|
||||
"@ethersproject/bytes": ">5.0.0-beta.0",
|
||||
"@ethersproject/logger": ">5.0.0-beta.0",
|
||||
"@ethersproject/networks": ">5.0.0-beta.0",
|
||||
"@ethersproject/properties": ">5.0.0-beta.0",
|
||||
"@ethersproject/transactions": ">5.0.0-beta.0",
|
||||
"@ethersproject/web": ">5.0.0-beta.0"
|
||||
"@ethersproject/bignumber": ">=5.0.0-beta.130",
|
||||
"@ethersproject/bytes": ">=5.0.0-beta.129",
|
||||
"@ethersproject/logger": ">=5.0.0-beta.129",
|
||||
"@ethersproject/networks": ">=5.0.0-beta.129",
|
||||
"@ethersproject/properties": ">=5.0.0-beta.131",
|
||||
"@ethersproject/transactions": ">=5.0.0-beta.128",
|
||||
"@ethersproject/web": ">=5.0.0-beta.129"
|
||||
},
|
||||
"keywords": [
|
||||
"Ethereum",
|
||||
@ -32,5 +28,7 @@
|
||||
"type": "git",
|
||||
"url": "git://github.com/ethers-io/ethers.js.git"
|
||||
},
|
||||
"tarballHash": "0x38d6dbab6c91fea9f20ed556d76842c9ac28e4542b997401d3e965156d1373e6"
|
||||
"module": "./lib.esm/index.js",
|
||||
"types": "./lib/index.d.ts",
|
||||
"tarballHash": "0x2beb1736c2a9c8023e74c415353bff10587ae1dc49240ec5dc2620171899f2e6"
|
||||
}
|
||||
|
@ -2,11 +2,10 @@
|
||||
"extends": "../../tsconfig.package.json",
|
||||
"compilerOptions": {
|
||||
"rootDir": "./src.ts",
|
||||
"outDir": "./"
|
||||
"outDir": "./lib/"
|
||||
},
|
||||
"include": [
|
||||
"./src.ts/*"
|
||||
"./src.ts/*"
|
||||
],
|
||||
"exclude": [ ]
|
||||
"exclude": []
|
||||
}
|
||||
|
||||
|
1
packages/abstract-signer/lib.esm/_version.js
Normal file
1
packages/abstract-signer/lib.esm/_version.js
Normal file
@ -0,0 +1 @@
|
||||
export const version = "abstract-signer/5.0.0-beta.131";
|
168
packages/abstract-signer/lib.esm/index.js
Normal file
168
packages/abstract-signer/lib.esm/index.js
Normal file
@ -0,0 +1,168 @@
|
||||
"use strict";
|
||||
import { defineReadOnly, resolveProperties, shallowCopy } from "@ethersproject/properties";
|
||||
import { Logger } from "@ethersproject/logger";
|
||||
import { version } from "./_version";
|
||||
const logger = new Logger(version);
|
||||
const allowedTransactionKeys = [
|
||||
"chainId", "data", "from", "gasLimit", "gasPrice", "nonce", "to", "value"
|
||||
];
|
||||
// Sub-Class Notes:
|
||||
// - A Signer MUST always make sure, that if present, the "from" field
|
||||
// matches the Signer, before sending or signing a transaction
|
||||
// - A Signer SHOULD always wrap private information (such as a private
|
||||
// key or mnemonic) in a function, so that console.log does not leak
|
||||
// the data
|
||||
export class Signer {
|
||||
///////////////////
|
||||
// Sub-classes MUST call super
|
||||
constructor() {
|
||||
logger.checkAbstract(new.target, Signer);
|
||||
defineReadOnly(this, "_isSigner", true);
|
||||
}
|
||||
///////////////////
|
||||
// Sub-classes MAY override these
|
||||
getBalance(blockTag) {
|
||||
this._checkProvider("getBalance");
|
||||
return this.provider.getBalance(this.getAddress(), blockTag);
|
||||
}
|
||||
getTransactionCount(blockTag) {
|
||||
this._checkProvider("getTransactionCount");
|
||||
return this.provider.getTransactionCount(this.getAddress(), blockTag);
|
||||
}
|
||||
// Populates "from" if unspecified, and estimates the gas for the transation
|
||||
estimateGas(transaction) {
|
||||
this._checkProvider("estimateGas");
|
||||
return resolveProperties(this.checkTransaction(transaction)).then((tx) => {
|
||||
return this.provider.estimateGas(tx);
|
||||
});
|
||||
}
|
||||
// Populates "from" if unspecified, and calls with the transation
|
||||
call(transaction, blockTag) {
|
||||
this._checkProvider("call");
|
||||
return resolveProperties(this.checkTransaction(transaction)).then((tx) => {
|
||||
return this.provider.call(tx);
|
||||
});
|
||||
}
|
||||
// Populates all fields in a transaction, signs it and sends it to the network
|
||||
sendTransaction(transaction) {
|
||||
this._checkProvider("sendTransaction");
|
||||
return this.populateTransaction(transaction).then((tx) => {
|
||||
return this.signTransaction(tx).then((signedTx) => {
|
||||
return this.provider.sendTransaction(signedTx);
|
||||
});
|
||||
});
|
||||
}
|
||||
getChainId() {
|
||||
this._checkProvider("getChainId");
|
||||
return this.provider.getNetwork().then((network) => network.chainId);
|
||||
}
|
||||
getGasPrice() {
|
||||
this._checkProvider("getGasPrice");
|
||||
return this.provider.getGasPrice();
|
||||
}
|
||||
resolveName(name) {
|
||||
this._checkProvider("resolveName");
|
||||
return this.provider.resolveName(name);
|
||||
}
|
||||
// Checks a transaction does not contain invalid keys and if
|
||||
// no "from" is provided, populates it.
|
||||
// - does NOT require a provider
|
||||
// - adds "from" is not present
|
||||
// - returns a COPY (safe to mutate the result)
|
||||
// By default called from: (overriding these prevents it)
|
||||
// - call
|
||||
// - estimateGas
|
||||
// - populateTransaction (and therefor sendTransaction)
|
||||
checkTransaction(transaction) {
|
||||
for (let key in transaction) {
|
||||
if (allowedTransactionKeys.indexOf(key) === -1) {
|
||||
logger.throwArgumentError("invalid transaction key: " + key, "transaction", transaction);
|
||||
}
|
||||
}
|
||||
let tx = shallowCopy(transaction);
|
||||
if (tx.from == null) {
|
||||
tx.from = this.getAddress();
|
||||
}
|
||||
return tx;
|
||||
}
|
||||
// Populates ALL keys for a transaction and checks that "from" matches
|
||||
// this Signer. Should be used by sendTransaction but NOT by signTransaction.
|
||||
// By default called from: (overriding these prevents it)
|
||||
// - sendTransaction
|
||||
populateTransaction(transaction) {
|
||||
return resolveProperties(this.checkTransaction(transaction)).then((tx) => {
|
||||
if (tx.to != null) {
|
||||
tx.to = Promise.resolve(tx.to).then((to) => this.resolveName(to));
|
||||
}
|
||||
if (tx.gasPrice == null) {
|
||||
tx.gasPrice = this.getGasPrice();
|
||||
}
|
||||
if (tx.nonce == null) {
|
||||
tx.nonce = this.getTransactionCount("pending");
|
||||
}
|
||||
// Make sure any provided address matches this signer
|
||||
if (tx.from == null) {
|
||||
tx.from = this.getAddress();
|
||||
}
|
||||
else {
|
||||
tx.from = Promise.all([
|
||||
this.getAddress(),
|
||||
this.provider.resolveName(tx.from)
|
||||
]).then((results) => {
|
||||
if (results[0] !== results[1]) {
|
||||
logger.throwArgumentError("from address mismatch", "transaction", transaction);
|
||||
}
|
||||
return results[0];
|
||||
});
|
||||
}
|
||||
if (tx.gasLimit == null) {
|
||||
tx.gasLimit = this.estimateGas(tx).catch((error) => {
|
||||
logger.throwError("cannot estimate gas; transaction may fail or may require manual gas limit", Logger.errors.UNPREDICTABLE_GAS_LIMIT, {
|
||||
tx: tx
|
||||
});
|
||||
});
|
||||
}
|
||||
if (tx.chainId == null) {
|
||||
tx.chainId = this.getChainId();
|
||||
}
|
||||
return resolveProperties(tx);
|
||||
});
|
||||
}
|
||||
///////////////////
|
||||
// Sub-classes SHOULD leave these alone
|
||||
_checkProvider(operation) {
|
||||
if (!this.provider) {
|
||||
logger.throwError("missing provider", Logger.errors.UNSUPPORTED_OPERATION, {
|
||||
operation: (operation || "_checkProvider")
|
||||
});
|
||||
}
|
||||
}
|
||||
static isSigner(value) {
|
||||
return !!(value && value._isSigner);
|
||||
}
|
||||
}
|
||||
export class VoidSigner extends Signer {
|
||||
constructor(address, provider) {
|
||||
logger.checkNew(new.target, VoidSigner);
|
||||
super();
|
||||
defineReadOnly(this, "address", address);
|
||||
defineReadOnly(this, "provider", provider || null);
|
||||
}
|
||||
getAddress() {
|
||||
return Promise.resolve(this.address);
|
||||
}
|
||||
_fail(message, operation) {
|
||||
return Promise.resolve().then(() => {
|
||||
logger.throwError(message, Logger.errors.UNSUPPORTED_OPERATION, { operation: operation });
|
||||
});
|
||||
}
|
||||
signMessage(message) {
|
||||
return this._fail("VoidSigner cannot sign messages", "signMessage");
|
||||
}
|
||||
signTransaction(transaction) {
|
||||
return this._fail("VoidSigner cannot sign transactions", "signTransaction");
|
||||
}
|
||||
connect(provider) {
|
||||
return new VoidSigner(this.address, provider);
|
||||
}
|
||||
}
|
1
packages/abstract-signer/lib/_version.d.ts
vendored
Normal file
1
packages/abstract-signer/lib/_version.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
||||
export declare const version = "abstract-signer/5.0.0-beta.131";
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user