epistery 1.3.8 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +65 -5
- package/dist/chains/Chain.d.ts +117 -0
- package/dist/chains/Chain.d.ts.map +1 -0
- package/dist/chains/Chain.js +175 -0
- package/dist/chains/Chain.js.map +1 -0
- package/dist/chains/EthereumChain.d.ts +18 -0
- package/dist/chains/EthereumChain.d.ts.map +1 -0
- package/dist/chains/EthereumChain.js +26 -0
- package/dist/chains/EthereumChain.js.map +1 -0
- package/dist/chains/JapanOpenChain.d.ts +21 -0
- package/dist/chains/JapanOpenChain.d.ts.map +1 -0
- package/dist/chains/JapanOpenChain.js +36 -0
- package/dist/chains/JapanOpenChain.js.map +1 -0
- package/dist/chains/PolygonChain.d.ts +31 -0
- package/dist/chains/PolygonChain.d.ts.map +1 -0
- package/dist/chains/PolygonChain.js +50 -0
- package/dist/chains/PolygonChain.js.map +1 -0
- package/dist/chains/index.d.ts +22 -0
- package/dist/chains/index.d.ts.map +1 -0
- package/dist/chains/index.js +39 -0
- package/dist/chains/index.js.map +1 -0
- package/dist/chains/registry.d.ts +21 -0
- package/dist/chains/registry.d.ts.map +1 -0
- package/dist/chains/registry.js +53 -0
- package/dist/chains/registry.js.map +1 -0
- package/dist/utils/Utils.d.ts.map +1 -1
- package/dist/utils/Utils.js +3 -2
- package/dist/utils/Utils.js.map +1 -1
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +1 -0
- package/dist/utils/index.js.map +1 -1
- package/index.mjs +2 -1
- package/package.json +1 -1
- package/src/chains/Chain.ts +221 -0
- package/src/chains/EthereumChain.ts +23 -0
- package/src/chains/JapanOpenChain.ts +37 -0
- package/src/chains/PolygonChain.ts +53 -0
- package/src/chains/README.md +109 -0
- package/src/chains/index.ts +27 -0
- package/src/chains/registry.ts +53 -0
- package/src/utils/Utils.ts +3 -2
- package/src/utils/index.ts +2 -1
package/README.md
CHANGED
|
@@ -198,13 +198,41 @@ email=you@example.com
|
|
|
198
198
|
[ipfs]
|
|
199
199
|
url=https://rootz.digital/api/v0
|
|
200
200
|
|
|
201
|
-
[default.provider]
|
|
202
|
-
chainId=420420422
|
|
203
|
-
name=polkadot-hub-testnet
|
|
204
|
-
rpc=https://testnet-passet-hub-eth-rpc.polkadot.io
|
|
205
|
-
|
|
206
201
|
[cli]
|
|
207
202
|
default_domain=localhost
|
|
203
|
+
|
|
204
|
+
# Legacy single provider (still supported):
|
|
205
|
+
[default.provider]
|
|
206
|
+
chainId=137
|
|
207
|
+
name=Polygon Mainnet
|
|
208
|
+
rpc=https://polygon-rpc.com
|
|
209
|
+
|
|
210
|
+
# Preferred: array of providers with public/private RPC separation.
|
|
211
|
+
# epistery-host uses this to populate the network selection dropdown
|
|
212
|
+
# and to inject private (API-key) RPCs for server-side calls.
|
|
213
|
+
|
|
214
|
+
[[default.providers]]
|
|
215
|
+
chainId=137
|
|
216
|
+
name=Polygon Mainnet
|
|
217
|
+
publicRpc=https://polygon-rpc.com
|
|
218
|
+
privateRpc=https://polygon-mainnet.g.alchemy.com/v2/YOUR_KEY
|
|
219
|
+
nativeCurrencyName=POL
|
|
220
|
+
nativeCurrencySymbol=POL
|
|
221
|
+
nativeCurrencyDecimals=18
|
|
222
|
+
|
|
223
|
+
[[default.providers]]
|
|
224
|
+
chainId=81
|
|
225
|
+
name=Japan Open Chain
|
|
226
|
+
publicRpc=https://rpc-2.japanopenchain.org:8545
|
|
227
|
+
nativeCurrencyName=JOC
|
|
228
|
+
nativeCurrencySymbol=JOC
|
|
229
|
+
nativeCurrencyDecimals=18
|
|
230
|
+
|
|
231
|
+
# Optional per-chain policy overrides (defaults are in code):
|
|
232
|
+
[default.providers.policy]
|
|
233
|
+
minPriorityFeeGwei=25
|
|
234
|
+
maxFeeMultiplier=2
|
|
235
|
+
gasLimitMultiplier=1.3
|
|
208
236
|
```
|
|
209
237
|
|
|
210
238
|
### Domain Config (`~/.epistery/mydomain.com/config.ini`)
|
|
@@ -298,11 +326,43 @@ Epistery follows a plugin architecture that integrates seamlessly with Express.j
|
|
|
298
326
|
- **Client Libraries** (`/client/*.js`): Browser-side authentication and data wallet tools
|
|
299
327
|
- **CLI** (`/cli/epistery.mjs`): Command-line interface for authenticated requests
|
|
300
328
|
- **Utils** (`/src/utils/`): Configuration, crypto operations, and Aqua protocol implementation
|
|
329
|
+
- **Chains** (`/src/chains/`): Per-chain provider, fee policy, and gas estimation
|
|
301
330
|
|
|
302
331
|
All endpoints follow RFC 8615 well-known URIs standard for service discovery.
|
|
303
332
|
|
|
304
333
|
See [Architecture.md](Architecture.md) for detailed architecture documentation.
|
|
305
334
|
|
|
335
|
+
### Chain Support
|
|
336
|
+
|
|
337
|
+
Each EVM chain epistery talks to is represented by a `Chain` object that owns the JSON-RPC provider, fee policy, and gas estimation strategy. Built-in chains:
|
|
338
|
+
|
|
339
|
+
| Chain | ID | Fee Model |
|
|
340
|
+
|-------|----|-----------|
|
|
341
|
+
| Polygon Mainnet | 137 | EIP-1559 with 25 gwei priority floor |
|
|
342
|
+
| Polygon Amoy | 80002 | EIP-1559 with 25 gwei priority floor |
|
|
343
|
+
| Ethereum Mainnet | 1 | Standard EIP-1559 |
|
|
344
|
+
| Sepolia Testnet | 11155111 | Standard EIP-1559 |
|
|
345
|
+
| Japan Open Chain | 81 | Legacy gasPrice with 30 gwei floor |
|
|
346
|
+
|
|
347
|
+
Use `chainFor()` to get a chain instance from a provider config:
|
|
348
|
+
|
|
349
|
+
```javascript
|
|
350
|
+
import { chainFor } from 'epistery';
|
|
351
|
+
|
|
352
|
+
const chain = chainFor(domainConfig.provider);
|
|
353
|
+
|
|
354
|
+
// Provider with explicit network info (no "could not detect network" errors)
|
|
355
|
+
const wallet = ethers.Wallet.fromMnemonic(mnemonic).connect(chain.provider);
|
|
356
|
+
|
|
357
|
+
// Per-chain fee data for transaction overrides
|
|
358
|
+
const feeData = await chain.getFeeData();
|
|
359
|
+
// → Polygon: { maxPriorityFeePerGas: 25 gwei, maxFeePerGas: 50 gwei }
|
|
360
|
+
// → JOC: { gasPrice: 30 gwei }
|
|
361
|
+
// → Ethereum: { maxPriorityFeePerGas: <network>, maxFeePerGas: <network> }
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
Adding a new chain is a single file — extend `Chain`, override the fee hooks that differ, and call `registerChain()`. No edits to existing code. See [src/chains/README.md](src/chains/README.md) for details.
|
|
365
|
+
|
|
306
366
|
## Use Cases
|
|
307
367
|
|
|
308
368
|
- **Decentralized Wikis**: User authentication and content ownership without central accounts
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { ethers } from 'ethers';
|
|
2
|
+
import { ProviderConfig } from '../utils/types';
|
|
3
|
+
/**
|
|
4
|
+
* Per-chain fee data, returned in the shape ethers v5 expects on a transaction.
|
|
5
|
+
* EIP-1559 chains return maxFeePerGas/maxPriorityFeePerGas.
|
|
6
|
+
* Legacy chains return gasPrice.
|
|
7
|
+
*/
|
|
8
|
+
export interface ChainFeeData {
|
|
9
|
+
maxFeePerGas?: ethers.BigNumber;
|
|
10
|
+
maxPriorityFeePerGas?: ethers.BigNumber;
|
|
11
|
+
gasPrice?: ethers.BigNumber;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Optional per-chain knobs that root config can override without editing code.
|
|
15
|
+
* Each subclass reads only what it cares about.
|
|
16
|
+
*/
|
|
17
|
+
export interface ChainPolicy {
|
|
18
|
+
minPriorityFeeGwei?: number;
|
|
19
|
+
maxFeeMultiplier?: number;
|
|
20
|
+
minGasPriceGwei?: number;
|
|
21
|
+
gasLimitMultiplier?: number;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Extended provider config that may carry per-chain policy + a private RPC URL.
|
|
25
|
+
* The plain `ProviderConfig` from utils/types stays the wire/storage shape;
|
|
26
|
+
* `ChainConfig` is what the Chain object actually holds in memory.
|
|
27
|
+
*/
|
|
28
|
+
export interface ChainConfig extends ProviderConfig {
|
|
29
|
+
publicRpc?: string;
|
|
30
|
+
privateRpc?: string;
|
|
31
|
+
policy?: ChainPolicy;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Base class for an EVM chain. Subclasses override only the policy hooks
|
|
35
|
+
* that are actually different from the EIP-1559 default.
|
|
36
|
+
*
|
|
37
|
+
* The Chain object owns:
|
|
38
|
+
* - the JsonRpcProvider (with explicit network info, fixing "could not detect network")
|
|
39
|
+
* - per-chain fee policy (getFeeData)
|
|
40
|
+
* - the contract Proxy that injects fee data into write calls
|
|
41
|
+
* - gas-limit estimation with a per-chain safety multiplier
|
|
42
|
+
*
|
|
43
|
+
* The Chain object does NOT own:
|
|
44
|
+
* - wallets / private keys
|
|
45
|
+
* - contract ABIs
|
|
46
|
+
* - domain config storage
|
|
47
|
+
*/
|
|
48
|
+
export declare class Chain {
|
|
49
|
+
readonly chainId: number;
|
|
50
|
+
readonly name: string;
|
|
51
|
+
readonly rpc: string;
|
|
52
|
+
readonly publicRpc: string | undefined;
|
|
53
|
+
readonly currency: {
|
|
54
|
+
name: string;
|
|
55
|
+
symbol: string;
|
|
56
|
+
decimals: number;
|
|
57
|
+
};
|
|
58
|
+
readonly policy: ChainPolicy;
|
|
59
|
+
private _provider;
|
|
60
|
+
constructor(config: ChainConfig);
|
|
61
|
+
/**
|
|
62
|
+
* Lazily-built provider with explicit network info.
|
|
63
|
+
* Passing `{ name, chainId }` to the JsonRpcProvider constructor avoids
|
|
64
|
+
* ethers' "could not detect network" error when the RPC is briefly
|
|
65
|
+
* unreachable at startup — ethers will skip its eth_chainId probe.
|
|
66
|
+
*/
|
|
67
|
+
get provider(): ethers.providers.JsonRpcProvider;
|
|
68
|
+
/** EIP-1559 by default. Subclasses override for legacy gasPrice chains. */
|
|
69
|
+
supportsEIP1559(): boolean;
|
|
70
|
+
/**
|
|
71
|
+
* Default fee policy: pass through whatever the network reports via
|
|
72
|
+
* eth_feeHistory / eth_gasPrice. Subclasses override to apply per-chain
|
|
73
|
+
* floors (Polygon's 25 gwei priority floor, JOC's gasPrice floor, etc.).
|
|
74
|
+
*/
|
|
75
|
+
getFeeData(): Promise<ChainFeeData>;
|
|
76
|
+
/**
|
|
77
|
+
* Estimate gas limit with this chain's safety multiplier.
|
|
78
|
+
* Used by callers that need to populate gasLimit explicitly (e.g. for
|
|
79
|
+
* pre-funding calculations). Most write calls will let ethers estimate
|
|
80
|
+
* automatically; this is for the cases where ethers' estimate is unsafe
|
|
81
|
+
* (Polygon Amoy, JOC) and a multiplier is required.
|
|
82
|
+
*/
|
|
83
|
+
estimateGas(populated: ethers.providers.TransactionRequest): Promise<ethers.BigNumber>;
|
|
84
|
+
/**
|
|
85
|
+
* Wrap an ethers.Contract so every state-mutating method automatically
|
|
86
|
+
* receives this chain's fee data as the transaction overrides argument.
|
|
87
|
+
*
|
|
88
|
+
* Uses Object.create (prototype chain) — the wrapper object gets its own
|
|
89
|
+
* writable properties for the write methods while reads of everything else
|
|
90
|
+
* (.address, .signer, view functions, .interface, etc.) fall through to
|
|
91
|
+
* the original contract via the prototype.
|
|
92
|
+
*
|
|
93
|
+
* Why not a Proxy: ethers v5 defines ABI methods with defineReadOnly
|
|
94
|
+
* (non-writable, non-configurable). V8's proxy invariant requires get
|
|
95
|
+
* traps to return the *original* value for such properties — returning a
|
|
96
|
+
* wrapped function throws TypeError. Object.create avoids this because
|
|
97
|
+
* the own properties on the child shadow the prototype's frozen ones.
|
|
98
|
+
*
|
|
99
|
+
* NOTE: epistery-host's DomainChain does NOT use this because all its
|
|
100
|
+
* write call sites already pass feeData explicitly. This method exists
|
|
101
|
+
* for other consumers (e.g. CLI tools, agents) that want automatic fee
|
|
102
|
+
* injection without threading overrides through every call.
|
|
103
|
+
*
|
|
104
|
+
* @param contract - the ethers.Contract instance
|
|
105
|
+
* @param abi - the same ABI used to construct the contract; needed to
|
|
106
|
+
* identify which methods are state-mutating.
|
|
107
|
+
*/
|
|
108
|
+
wrapContract<T extends ethers.Contract>(contract: T, abi: ReadonlyArray<any>): T;
|
|
109
|
+
/**
|
|
110
|
+
* Recognize a transaction-overrides object so we don't mistake it for a
|
|
111
|
+
* positional argument. Excludes BigNumbers and arrays explicitly.
|
|
112
|
+
*/
|
|
113
|
+
static isOverridesObject(x: any): boolean;
|
|
114
|
+
/** Convenience: gwei → BigNumber wei */
|
|
115
|
+
protected gwei(n: number): ethers.BigNumber;
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=Chain.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Chain.d.ts","sourceRoot":"","sources":["../../src/chains/Chain.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAEhD;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC,SAAS,CAAC;IAChC,oBAAoB,CAAC,EAAE,MAAM,CAAC,SAAS,CAAC;IACxC,QAAQ,CAAC,EAAE,MAAM,CAAC,SAAS,CAAC;CAC7B;AAED;;;GAGG;AACH,MAAM,WAAW,WAAW;IAE1B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;;;GAIG;AACH,MAAM,WAAW,WAAY,SAAQ,cAAc;IACjD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED;;;;;;;;;;;;;;GAcG;AACH,qBAAa,KAAK;IAChB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IACvC,QAAQ,CAAC,QAAQ,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IACtE,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAE7B,OAAO,CAAC,SAAS,CAAiD;gBAEtD,MAAM,EAAE,WAAW;IAgB/B;;;;;OAKG;IACH,IAAI,QAAQ,IAAI,MAAM,CAAC,SAAS,CAAC,eAAe,CAQ/C;IAED,2EAA2E;IAC3E,eAAe,IAAI,OAAO;IAI1B;;;;OAIG;IACG,UAAU,IAAI,OAAO,CAAC,YAAY,CAAC;IAczC;;;;;;OAMG;IACG,WAAW,CACf,SAAS,EAAE,MAAM,CAAC,SAAS,CAAC,kBAAkB,GAC7C,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC;IAQ5B;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACH,YAAY,CAAC,CAAC,SAAS,MAAM,CAAC,QAAQ,EAAE,QAAQ,EAAE,CAAC,EAAE,GAAG,EAAE,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC;IAmChF;;;OAGG;IACH,MAAM,CAAC,iBAAiB,CAAC,CAAC,EAAE,GAAG,GAAG,OAAO;IAgBzC,wCAAwC;IACxC,SAAS,CAAC,IAAI,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,SAAS;CAG5C"}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Chain = void 0;
|
|
4
|
+
const ethers_1 = require("ethers");
|
|
5
|
+
/**
|
|
6
|
+
* Base class for an EVM chain. Subclasses override only the policy hooks
|
|
7
|
+
* that are actually different from the EIP-1559 default.
|
|
8
|
+
*
|
|
9
|
+
* The Chain object owns:
|
|
10
|
+
* - the JsonRpcProvider (with explicit network info, fixing "could not detect network")
|
|
11
|
+
* - per-chain fee policy (getFeeData)
|
|
12
|
+
* - the contract Proxy that injects fee data into write calls
|
|
13
|
+
* - gas-limit estimation with a per-chain safety multiplier
|
|
14
|
+
*
|
|
15
|
+
* The Chain object does NOT own:
|
|
16
|
+
* - wallets / private keys
|
|
17
|
+
* - contract ABIs
|
|
18
|
+
* - domain config storage
|
|
19
|
+
*/
|
|
20
|
+
class Chain {
|
|
21
|
+
constructor(config) {
|
|
22
|
+
this._provider = null;
|
|
23
|
+
if (config.chainId == null) {
|
|
24
|
+
throw new Error(`Chain config missing chainId: ${JSON.stringify(config)}`);
|
|
25
|
+
}
|
|
26
|
+
this.chainId = Number(config.chainId);
|
|
27
|
+
this.name = config.name;
|
|
28
|
+
this.rpc = config.privateRpc || config.rpc;
|
|
29
|
+
this.publicRpc = config.publicRpc || config.rpc;
|
|
30
|
+
this.currency = {
|
|
31
|
+
name: config.nativeCurrencyName || '',
|
|
32
|
+
symbol: config.nativeCurrencySymbol || '',
|
|
33
|
+
decimals: config.nativeCurrencyDecimals || 18,
|
|
34
|
+
};
|
|
35
|
+
this.policy = config.policy || {};
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Lazily-built provider with explicit network info.
|
|
39
|
+
* Passing `{ name, chainId }` to the JsonRpcProvider constructor avoids
|
|
40
|
+
* ethers' "could not detect network" error when the RPC is briefly
|
|
41
|
+
* unreachable at startup — ethers will skip its eth_chainId probe.
|
|
42
|
+
*/
|
|
43
|
+
get provider() {
|
|
44
|
+
if (!this._provider) {
|
|
45
|
+
this._provider = new ethers_1.ethers.providers.JsonRpcProvider(this.rpc, {
|
|
46
|
+
name: this.name,
|
|
47
|
+
chainId: this.chainId,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
return this._provider;
|
|
51
|
+
}
|
|
52
|
+
/** EIP-1559 by default. Subclasses override for legacy gasPrice chains. */
|
|
53
|
+
supportsEIP1559() {
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Default fee policy: pass through whatever the network reports via
|
|
58
|
+
* eth_feeHistory / eth_gasPrice. Subclasses override to apply per-chain
|
|
59
|
+
* floors (Polygon's 25 gwei priority floor, JOC's gasPrice floor, etc.).
|
|
60
|
+
*/
|
|
61
|
+
async getFeeData() {
|
|
62
|
+
const fd = await this.provider.getFeeData();
|
|
63
|
+
if (this.supportsEIP1559() && fd.maxFeePerGas && fd.maxPriorityFeePerGas) {
|
|
64
|
+
return {
|
|
65
|
+
maxFeePerGas: fd.maxFeePerGas,
|
|
66
|
+
maxPriorityFeePerGas: fd.maxPriorityFeePerGas,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
if (fd.gasPrice) {
|
|
70
|
+
return { gasPrice: fd.gasPrice };
|
|
71
|
+
}
|
|
72
|
+
throw new Error(`Chain ${this.name} (${this.chainId}) returned no usable fee data`);
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Estimate gas limit with this chain's safety multiplier.
|
|
76
|
+
* Used by callers that need to populate gasLimit explicitly (e.g. for
|
|
77
|
+
* pre-funding calculations). Most write calls will let ethers estimate
|
|
78
|
+
* automatically; this is for the cases where ethers' estimate is unsafe
|
|
79
|
+
* (Polygon Amoy, JOC) and a multiplier is required.
|
|
80
|
+
*/
|
|
81
|
+
async estimateGas(populated) {
|
|
82
|
+
const estimate = await this.provider.estimateGas(populated);
|
|
83
|
+
const multiplier = this.policy.gasLimitMultiplier ?? 1.3;
|
|
84
|
+
// Multiply via integer math to stay in BigNumber-land.
|
|
85
|
+
const num = Math.round(multiplier * 100);
|
|
86
|
+
return estimate.mul(num).div(100);
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Wrap an ethers.Contract so every state-mutating method automatically
|
|
90
|
+
* receives this chain's fee data as the transaction overrides argument.
|
|
91
|
+
*
|
|
92
|
+
* Uses Object.create (prototype chain) — the wrapper object gets its own
|
|
93
|
+
* writable properties for the write methods while reads of everything else
|
|
94
|
+
* (.address, .signer, view functions, .interface, etc.) fall through to
|
|
95
|
+
* the original contract via the prototype.
|
|
96
|
+
*
|
|
97
|
+
* Why not a Proxy: ethers v5 defines ABI methods with defineReadOnly
|
|
98
|
+
* (non-writable, non-configurable). V8's proxy invariant requires get
|
|
99
|
+
* traps to return the *original* value for such properties — returning a
|
|
100
|
+
* wrapped function throws TypeError. Object.create avoids this because
|
|
101
|
+
* the own properties on the child shadow the prototype's frozen ones.
|
|
102
|
+
*
|
|
103
|
+
* NOTE: epistery-host's DomainChain does NOT use this because all its
|
|
104
|
+
* write call sites already pass feeData explicitly. This method exists
|
|
105
|
+
* for other consumers (e.g. CLI tools, agents) that want automatic fee
|
|
106
|
+
* injection without threading overrides through every call.
|
|
107
|
+
*
|
|
108
|
+
* @param contract - the ethers.Contract instance
|
|
109
|
+
* @param abi - the same ABI used to construct the contract; needed to
|
|
110
|
+
* identify which methods are state-mutating.
|
|
111
|
+
*/
|
|
112
|
+
wrapContract(contract, abi) {
|
|
113
|
+
const writeFns = new Set();
|
|
114
|
+
for (const item of abi) {
|
|
115
|
+
if (item.type !== 'function')
|
|
116
|
+
continue;
|
|
117
|
+
if (item.stateMutability === 'view' || item.stateMutability === 'pure')
|
|
118
|
+
continue;
|
|
119
|
+
if (typeof item.name === 'string')
|
|
120
|
+
writeFns.add(item.name);
|
|
121
|
+
}
|
|
122
|
+
const chain = this;
|
|
123
|
+
const wrapped = Object.create(contract);
|
|
124
|
+
for (const name of writeFns) {
|
|
125
|
+
const original = contract[name];
|
|
126
|
+
if (typeof original !== 'function')
|
|
127
|
+
continue;
|
|
128
|
+
Object.defineProperty(wrapped, name, {
|
|
129
|
+
value: async function (...args) {
|
|
130
|
+
let overrides;
|
|
131
|
+
const last = args[args.length - 1];
|
|
132
|
+
if (Chain.isOverridesObject(last)) {
|
|
133
|
+
const fee = await chain.getFeeData();
|
|
134
|
+
overrides = { ...fee, ...last };
|
|
135
|
+
args[args.length - 1] = overrides;
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
overrides = await chain.getFeeData();
|
|
139
|
+
args.push(overrides);
|
|
140
|
+
}
|
|
141
|
+
return original.apply(contract, args);
|
|
142
|
+
},
|
|
143
|
+
writable: true,
|
|
144
|
+
configurable: true,
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
return wrapped;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Recognize a transaction-overrides object so we don't mistake it for a
|
|
151
|
+
* positional argument. Excludes BigNumbers and arrays explicitly.
|
|
152
|
+
*/
|
|
153
|
+
static isOverridesObject(x) {
|
|
154
|
+
if (!x || typeof x !== 'object')
|
|
155
|
+
return false;
|
|
156
|
+
if (Array.isArray(x))
|
|
157
|
+
return false;
|
|
158
|
+
if (ethers_1.ethers.BigNumber.isBigNumber(x))
|
|
159
|
+
return false;
|
|
160
|
+
return ('gasPrice' in x ||
|
|
161
|
+
'maxFeePerGas' in x ||
|
|
162
|
+
'maxPriorityFeePerGas' in x ||
|
|
163
|
+
'gasLimit' in x ||
|
|
164
|
+
'nonce' in x ||
|
|
165
|
+
'value' in x ||
|
|
166
|
+
'from' in x ||
|
|
167
|
+
'type' in x);
|
|
168
|
+
}
|
|
169
|
+
/** Convenience: gwei → BigNumber wei */
|
|
170
|
+
gwei(n) {
|
|
171
|
+
return ethers_1.ethers.utils.parseUnits(String(n), 'gwei');
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
exports.Chain = Chain;
|
|
175
|
+
//# sourceMappingURL=Chain.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Chain.js","sourceRoot":"","sources":["../../src/chains/Chain.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Chain } from './Chain';
|
|
2
|
+
/**
|
|
3
|
+
* Ethereum mainnet (chainId 1).
|
|
4
|
+
*
|
|
5
|
+
* Standard EIP-1559 behavior — ethers' getFeeData is accurate here.
|
|
6
|
+
* No floors, no special multipliers. The base class default works as-is;
|
|
7
|
+
* this subclass exists for the registry and for future overrides.
|
|
8
|
+
*/
|
|
9
|
+
export declare class EthereumChain extends Chain {
|
|
10
|
+
static chainId: number;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Sepolia testnet (chainId 11155111). Same behavior as Ethereum mainnet.
|
|
14
|
+
*/
|
|
15
|
+
export declare class SepoliaChain extends Chain {
|
|
16
|
+
static chainId: number;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=EthereumChain.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EthereumChain.d.ts","sourceRoot":"","sources":["../../src/chains/EthereumChain.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAGhC;;;;;;GAMG;AACH,qBAAa,aAAc,SAAQ,KAAK;IACtC,MAAM,CAAC,OAAO,SAAK;CACpB;AAED;;GAEG;AACH,qBAAa,YAAa,SAAQ,KAAK;IACrC,MAAM,CAAC,OAAO,SAAY;CAC3B"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SepoliaChain = exports.EthereumChain = void 0;
|
|
4
|
+
const Chain_1 = require("./Chain");
|
|
5
|
+
const registry_1 = require("./registry");
|
|
6
|
+
/**
|
|
7
|
+
* Ethereum mainnet (chainId 1).
|
|
8
|
+
*
|
|
9
|
+
* Standard EIP-1559 behavior — ethers' getFeeData is accurate here.
|
|
10
|
+
* No floors, no special multipliers. The base class default works as-is;
|
|
11
|
+
* this subclass exists for the registry and for future overrides.
|
|
12
|
+
*/
|
|
13
|
+
class EthereumChain extends Chain_1.Chain {
|
|
14
|
+
}
|
|
15
|
+
exports.EthereumChain = EthereumChain;
|
|
16
|
+
EthereumChain.chainId = 1;
|
|
17
|
+
/**
|
|
18
|
+
* Sepolia testnet (chainId 11155111). Same behavior as Ethereum mainnet.
|
|
19
|
+
*/
|
|
20
|
+
class SepoliaChain extends Chain_1.Chain {
|
|
21
|
+
}
|
|
22
|
+
exports.SepoliaChain = SepoliaChain;
|
|
23
|
+
SepoliaChain.chainId = 11155111;
|
|
24
|
+
(0, registry_1.registerChain)(EthereumChain.chainId, EthereumChain);
|
|
25
|
+
(0, registry_1.registerChain)(SepoliaChain.chainId, SepoliaChain);
|
|
26
|
+
//# sourceMappingURL=EthereumChain.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EthereumChain.js","sourceRoot":"","sources":["../../src/chains/EthereumChain.ts"],"names":[],"mappings":";;;AAAA,mCAAgC;AAChC,yCAA2C;AAE3C;;;;;;GAMG;AACH,MAAa,aAAc,SAAQ,aAAK;;AAAxC,sCAEC;AADQ,qBAAO,GAAG,CAAC,CAAC;AAGrB;;GAEG;AACH,MAAa,YAAa,SAAQ,aAAK;;AAAvC,oCAEC;AADQ,oBAAO,GAAG,QAAQ,CAAC;AAG5B,IAAA,wBAAa,EAAC,aAAa,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;AACpD,IAAA,wBAAa,EAAC,YAAY,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { ethers } from 'ethers';
|
|
2
|
+
import { Chain, ChainFeeData } from './Chain';
|
|
3
|
+
/**
|
|
4
|
+
* Japan Open Chain (chainId 81).
|
|
5
|
+
*
|
|
6
|
+
* Why this class exists: JOC is a legacy gasPrice chain. Its base fee is
|
|
7
|
+
* effectively zero, but the RPC enforces a high *minimum* gas price (around
|
|
8
|
+
* 30 gwei). EIP-1559 fields are not honored — submitting a transaction with
|
|
9
|
+
* maxFeePerGas/maxPriorityFeePerGas instead of gasPrice gets rejected.
|
|
10
|
+
*
|
|
11
|
+
* The base class would happily try to use EIP-1559; we override
|
|
12
|
+
* supportsEIP1559() to false and return only `gasPrice`, clamped to the
|
|
13
|
+
* configured floor.
|
|
14
|
+
*/
|
|
15
|
+
export declare class JapanOpenChain extends Chain {
|
|
16
|
+
static chainId: number;
|
|
17
|
+
supportsEIP1559(): boolean;
|
|
18
|
+
protected minGasPrice(): ethers.BigNumber;
|
|
19
|
+
getFeeData(): Promise<ChainFeeData>;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=JapanOpenChain.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"JapanOpenChain.d.ts","sourceRoot":"","sources":["../../src/chains/JapanOpenChain.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAG9C;;;;;;;;;;;GAWG;AACH,qBAAa,cAAe,SAAQ,KAAK;IACvC,MAAM,CAAC,OAAO,SAAM;IAEpB,eAAe,IAAI,OAAO;IAI1B,SAAS,CAAC,WAAW,IAAI,MAAM,CAAC,SAAS;IAInC,UAAU,IAAI,OAAO,CAAC,YAAY,CAAC;CAO1C"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.JapanOpenChain = void 0;
|
|
4
|
+
const Chain_1 = require("./Chain");
|
|
5
|
+
const registry_1 = require("./registry");
|
|
6
|
+
/**
|
|
7
|
+
* Japan Open Chain (chainId 81).
|
|
8
|
+
*
|
|
9
|
+
* Why this class exists: JOC is a legacy gasPrice chain. Its base fee is
|
|
10
|
+
* effectively zero, but the RPC enforces a high *minimum* gas price (around
|
|
11
|
+
* 30 gwei). EIP-1559 fields are not honored — submitting a transaction with
|
|
12
|
+
* maxFeePerGas/maxPriorityFeePerGas instead of gasPrice gets rejected.
|
|
13
|
+
*
|
|
14
|
+
* The base class would happily try to use EIP-1559; we override
|
|
15
|
+
* supportsEIP1559() to false and return only `gasPrice`, clamped to the
|
|
16
|
+
* configured floor.
|
|
17
|
+
*/
|
|
18
|
+
class JapanOpenChain extends Chain_1.Chain {
|
|
19
|
+
supportsEIP1559() {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
minGasPrice() {
|
|
23
|
+
return this.gwei(this.policy.minGasPriceGwei ?? 30);
|
|
24
|
+
}
|
|
25
|
+
async getFeeData() {
|
|
26
|
+
const fd = await this.provider.getFeeData();
|
|
27
|
+
const floor = this.minGasPrice();
|
|
28
|
+
const networkPrice = fd.gasPrice ?? floor;
|
|
29
|
+
const gasPrice = networkPrice.gt(floor) ? networkPrice : floor;
|
|
30
|
+
return { gasPrice };
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
exports.JapanOpenChain = JapanOpenChain;
|
|
34
|
+
JapanOpenChain.chainId = 81;
|
|
35
|
+
(0, registry_1.registerChain)(JapanOpenChain.chainId, JapanOpenChain);
|
|
36
|
+
//# sourceMappingURL=JapanOpenChain.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"JapanOpenChain.js","sourceRoot":"","sources":["../../src/chains/JapanOpenChain.ts"],"names":[],"mappings":";;;AACA,mCAA8C;AAC9C,yCAA2C;AAE3C;;;;;;;;;;;GAWG;AACH,MAAa,cAAe,SAAQ,aAAK;IAGvC,eAAe;QACb,OAAO,KAAK,CAAC;IACf,CAAC;IAES,WAAW;QACnB,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,eAAe,IAAI,EAAE,CAAC,CAAC;IACtD,CAAC;IAED,KAAK,CAAC,UAAU;QACd,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC;QAC5C,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;QACjC,MAAM,YAAY,GAAG,EAAE,CAAC,QAAQ,IAAI,KAAK,CAAC;QAC1C,MAAM,QAAQ,GAAG,YAAY,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC;QAC/D,OAAO,EAAE,QAAQ,EAAE,CAAC;IACtB,CAAC;;AAjBH,wCAkBC;AAjBQ,sBAAO,GAAG,EAAE,CAAC;AAmBtB,IAAA,wBAAa,EAAC,cAAc,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { ethers } from 'ethers';
|
|
2
|
+
import { Chain, ChainFeeData } from './Chain';
|
|
3
|
+
/**
|
|
4
|
+
* Polygon mainnet (chainId 137).
|
|
5
|
+
*
|
|
6
|
+
* Why this class exists: Polygon enforces a hard 25 gwei minimum priority fee
|
|
7
|
+
* at the RPC level. Transactions submitted with a lower priority fee are
|
|
8
|
+
* rejected with "max fee per gas less than block base fee" or simply silently
|
|
9
|
+
* dropped. ethers v5's getFeeData() does NOT know about this floor and will
|
|
10
|
+
* happily return ~1.5 gwei from eth_feeHistory.
|
|
11
|
+
*
|
|
12
|
+
* The fix: clamp maxPriorityFeePerGas to at least 25 gwei (overridable via
|
|
13
|
+
* policy.minPriorityFeeGwei in root config) and ensure maxFeePerGas >=
|
|
14
|
+
* 2 * maxPriorityFeePerGas.
|
|
15
|
+
*/
|
|
16
|
+
export declare class PolygonChain extends Chain {
|
|
17
|
+
static chainId: number;
|
|
18
|
+
protected minPriorityFee(): ethers.BigNumber;
|
|
19
|
+
getFeeData(): Promise<ChainFeeData>;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Polygon Amoy testnet (chainId 80002).
|
|
23
|
+
*
|
|
24
|
+
* Same fee floor concerns as Polygon mainnet — Amoy is the canonical Polygon
|
|
25
|
+
* PoS testnet and the RPC enforces an identical 25 gwei priority floor.
|
|
26
|
+
* Subclassing PolygonChain keeps the policy in one place.
|
|
27
|
+
*/
|
|
28
|
+
export declare class AmoyChain extends PolygonChain {
|
|
29
|
+
static chainId: number;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=PolygonChain.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PolygonChain.d.ts","sourceRoot":"","sources":["../../src/chains/PolygonChain.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAG9C;;;;;;;;;;;;GAYG;AACH,qBAAa,YAAa,SAAQ,KAAK;IACrC,MAAM,CAAC,OAAO,SAAO;IAErB,SAAS,CAAC,cAAc,IAAI,MAAM,CAAC,SAAS;IAItC,UAAU,IAAI,OAAO,CAAC,YAAY,CAAC;CAc1C;AAED;;;;;;GAMG;AACH,qBAAa,SAAU,SAAQ,YAAY;IACzC,MAAM,CAAC,OAAO,SAAS;CACxB"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AmoyChain = exports.PolygonChain = void 0;
|
|
4
|
+
const Chain_1 = require("./Chain");
|
|
5
|
+
const registry_1 = require("./registry");
|
|
6
|
+
/**
|
|
7
|
+
* Polygon mainnet (chainId 137).
|
|
8
|
+
*
|
|
9
|
+
* Why this class exists: Polygon enforces a hard 25 gwei minimum priority fee
|
|
10
|
+
* at the RPC level. Transactions submitted with a lower priority fee are
|
|
11
|
+
* rejected with "max fee per gas less than block base fee" or simply silently
|
|
12
|
+
* dropped. ethers v5's getFeeData() does NOT know about this floor and will
|
|
13
|
+
* happily return ~1.5 gwei from eth_feeHistory.
|
|
14
|
+
*
|
|
15
|
+
* The fix: clamp maxPriorityFeePerGas to at least 25 gwei (overridable via
|
|
16
|
+
* policy.minPriorityFeeGwei in root config) and ensure maxFeePerGas >=
|
|
17
|
+
* 2 * maxPriorityFeePerGas.
|
|
18
|
+
*/
|
|
19
|
+
class PolygonChain extends Chain_1.Chain {
|
|
20
|
+
minPriorityFee() {
|
|
21
|
+
return this.gwei(this.policy.minPriorityFeeGwei ?? 25);
|
|
22
|
+
}
|
|
23
|
+
async getFeeData() {
|
|
24
|
+
const fd = await this.provider.getFeeData();
|
|
25
|
+
const floor = this.minPriorityFee();
|
|
26
|
+
const networkPriority = fd.maxPriorityFeePerGas ?? floor;
|
|
27
|
+
const maxPriorityFeePerGas = networkPriority.gt(floor) ? networkPriority : floor;
|
|
28
|
+
const multiplier = this.policy.maxFeeMultiplier ?? 2;
|
|
29
|
+
const minMaxFee = maxPriorityFeePerGas.mul(multiplier);
|
|
30
|
+
const networkMax = fd.maxFeePerGas ?? minMaxFee;
|
|
31
|
+
const maxFeePerGas = networkMax.gt(minMaxFee) ? networkMax : minMaxFee;
|
|
32
|
+
return { maxPriorityFeePerGas, maxFeePerGas };
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
exports.PolygonChain = PolygonChain;
|
|
36
|
+
PolygonChain.chainId = 137;
|
|
37
|
+
/**
|
|
38
|
+
* Polygon Amoy testnet (chainId 80002).
|
|
39
|
+
*
|
|
40
|
+
* Same fee floor concerns as Polygon mainnet — Amoy is the canonical Polygon
|
|
41
|
+
* PoS testnet and the RPC enforces an identical 25 gwei priority floor.
|
|
42
|
+
* Subclassing PolygonChain keeps the policy in one place.
|
|
43
|
+
*/
|
|
44
|
+
class AmoyChain extends PolygonChain {
|
|
45
|
+
}
|
|
46
|
+
exports.AmoyChain = AmoyChain;
|
|
47
|
+
AmoyChain.chainId = 80002;
|
|
48
|
+
(0, registry_1.registerChain)(PolygonChain.chainId, PolygonChain);
|
|
49
|
+
(0, registry_1.registerChain)(AmoyChain.chainId, AmoyChain);
|
|
50
|
+
//# sourceMappingURL=PolygonChain.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PolygonChain.js","sourceRoot":"","sources":["../../src/chains/PolygonChain.ts"],"names":[],"mappings":";;;AACA,mCAA8C;AAC9C,yCAA2C;AAE3C;;;;;;;;;;;;GAYG;AACH,MAAa,YAAa,SAAQ,aAAK;IAG3B,cAAc;QACtB,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,kBAAkB,IAAI,EAAE,CAAC,CAAC;IACzD,CAAC;IAED,KAAK,CAAC,UAAU;QACd,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC;QAC5C,MAAM,KAAK,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;QAEpC,MAAM,eAAe,GAAG,EAAE,CAAC,oBAAoB,IAAI,KAAK,CAAC;QACzD,MAAM,oBAAoB,GAAG,eAAe,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,KAAK,CAAC;QAEjF,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,gBAAgB,IAAI,CAAC,CAAC;QACrD,MAAM,SAAS,GAAG,oBAAoB,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QACvD,MAAM,UAAU,GAAG,EAAE,CAAC,YAAY,IAAI,SAAS,CAAC;QAChD,MAAM,YAAY,GAAG,UAAU,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC;QAEvE,OAAO,EAAE,oBAAoB,EAAE,YAAY,EAAE,CAAC;IAChD,CAAC;;AApBH,oCAqBC;AApBQ,oBAAO,GAAG,GAAG,CAAC;AAsBvB;;;;;;GAMG;AACH,MAAa,SAAU,SAAQ,YAAY;;AAA3C,8BAEC;AADQ,iBAAO,GAAG,KAAK,CAAC;AAGzB,IAAA,wBAAa,EAAC,YAAY,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;AAClD,IAAA,wBAAa,EAAC,SAAS,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Chains module barrel.
|
|
3
|
+
*
|
|
4
|
+
* Exports the public API and pulls in the built-in chain subclasses for
|
|
5
|
+
* their side-effect (each subclass calls registerChain() at module load).
|
|
6
|
+
*
|
|
7
|
+
* Adding a new built-in chain: drop a `MyChain.ts` next to this file that
|
|
8
|
+
* extends Chain and calls `registerChain(MyChain.chainId, MyChain)` at the
|
|
9
|
+
* bottom, then add one `import './MyChain';` line below. No edits to
|
|
10
|
+
* Chain.ts or registry.ts.
|
|
11
|
+
*
|
|
12
|
+
* Adding a chain from outside this package: write the same kind of file in
|
|
13
|
+
* your own codebase and `import 'your-package/dist/chains/MyChain';` at app
|
|
14
|
+
* startup. The Map in registry.ts is module-scoped, so the registration
|
|
15
|
+
* happens exactly once.
|
|
16
|
+
*/
|
|
17
|
+
export { Chain, ChainConfig, ChainFeeData, ChainPolicy } from './Chain';
|
|
18
|
+
export { chainFor, registerChain, hasRegisteredChain, registeredChainIds } from './registry';
|
|
19
|
+
export { PolygonChain, AmoyChain } from './PolygonChain';
|
|
20
|
+
export { EthereumChain, SepoliaChain } from './EthereumChain';
|
|
21
|
+
export { JapanOpenChain } from './JapanOpenChain';
|
|
22
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/chains/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACxE,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAK7F,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC"}
|