crypto-aio 0.1.0 → 0.2.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/CHANGELOG.md +151 -1
- package/README.md +32 -12
- package/dist/adapters/evm/builder.js +64 -4
- package/dist/adapters/evm/builder.js.map +1 -1
- package/dist/adapters/evm/decode.js +6 -1
- package/dist/adapters/evm/decode.js.map +1 -1
- package/dist/adapters/evm/ethers-client.js +4 -0
- package/dist/adapters/evm/ethers-client.js.map +1 -1
- package/dist/adapters/evm/fees.d.ts +24 -0
- package/dist/adapters/evm/fees.js +47 -4
- package/dist/adapters/evm/fees.js.map +1 -1
- package/dist/adapters/evm/index.d.ts +1 -1
- package/dist/adapters/evm/index.js +2 -1
- package/dist/adapters/evm/index.js.map +1 -1
- package/dist/adapters/evm/network.d.ts +5 -0
- package/dist/adapters/evm/network.js +21 -2
- package/dist/adapters/evm/network.js.map +1 -1
- package/dist/adapters/evm/plugin.d.ts +5 -6
- package/dist/adapters/evm/plugin.js +50 -2
- package/dist/adapters/evm/plugin.js.map +1 -1
- package/dist/adapters/evm/proofs.js +17 -5
- package/dist/adapters/evm/proofs.js.map +1 -1
- package/dist/adapters/evm/reader.d.ts +18 -0
- package/dist/adapters/evm/reader.js +34 -0
- package/dist/adapters/evm/reader.js.map +1 -1
- package/dist/adapters/evm/tokens.d.ts +3 -0
- package/dist/adapters/evm/tokens.js.map +1 -1
- package/dist/adapters/evm/types.d.ts +10 -0
- package/dist/adapters/evm/types.js.map +1 -1
- package/dist/adapters/evm/web3-client.d.ts +6 -3
- package/dist/adapters/evm/web3-client.js +19 -2
- package/dist/adapters/evm/web3-client.js.map +1 -1
- package/dist/adapters/solana/builder.js +29 -18
- package/dist/adapters/solana/builder.js.map +1 -1
- package/dist/adapters/solana/fees.d.ts +12 -3
- package/dist/adapters/solana/fees.js +13 -4
- package/dist/adapters/solana/fees.js.map +1 -1
- package/dist/adapters/solana/message.d.ts +15 -0
- package/dist/adapters/solana/message.js +120 -0
- package/dist/adapters/solana/message.js.map +1 -0
- package/dist/adapters/solana/plugin.js +4 -1
- package/dist/adapters/solana/plugin.js.map +1 -1
- package/dist/adapters/solana/types.d.ts +8 -5
- package/dist/adapters/solana/types.js.map +1 -1
- package/dist/adapters/solana/web3.js +10 -32
- package/dist/adapters/solana/web3.js.map +1 -1
- package/dist/adapters/ton/proofs.js +18 -76
- package/dist/adapters/ton/proofs.js.map +1 -1
- package/dist/adapters/ton/reader.d.ts +45 -4
- package/dist/adapters/ton/reader.js +200 -5
- package/dist/adapters/ton/reader.js.map +1 -1
- package/dist/adapters/ton/trace.d.ts +26 -0
- package/dist/adapters/ton/trace.js +35 -9
- package/dist/adapters/ton/trace.js.map +1 -1
- package/dist/adapters/tron/abi.d.ts +2 -0
- package/dist/adapters/tron/abi.js +2 -0
- package/dist/adapters/tron/abi.js.map +1 -1
- package/dist/adapters/tron/builder.js +20 -4
- package/dist/adapters/tron/builder.js.map +1 -1
- package/dist/adapters/tron/decode.d.ts +2 -0
- package/dist/adapters/tron/decode.js +1 -1
- package/dist/adapters/tron/decode.js.map +1 -1
- package/dist/adapters/tron/proofs.js +1 -0
- package/dist/adapters/tron/proofs.js.map +1 -1
- package/dist/adapters/tron/reader.d.ts +10 -0
- package/dist/adapters/tron/reader.js +17 -0
- package/dist/adapters/tron/reader.js.map +1 -1
- package/dist/adapters/tron/tokens.d.ts +2 -0
- package/dist/adapters/tron/tokens.js.map +1 -1
- package/dist/adapters/utxo/builder.js +1 -1
- package/dist/adapters/utxo/builder.js.map +1 -1
- package/dist/adapters/utxo/chains.js +2 -1
- package/dist/adapters/utxo/chains.js.map +1 -1
- package/dist/adapters/utxo/context.d.ts +6 -0
- package/dist/adapters/utxo/context.js +8 -1
- package/dist/adapters/utxo/context.js.map +1 -1
- package/dist/adapters/utxo/decode.d.ts +8 -0
- package/dist/adapters/utxo/decode.js +36 -0
- package/dist/adapters/utxo/decode.js.map +1 -1
- package/dist/adapters/utxo/driver.js +5 -0
- package/dist/adapters/utxo/driver.js.map +1 -1
- package/dist/adapters/utxo/esplora.d.ts +23 -2
- package/dist/adapters/utxo/esplora.js +49 -2
- package/dist/adapters/utxo/esplora.js.map +1 -1
- package/dist/adapters/utxo/proofs.d.ts +15 -6
- package/dist/adapters/utxo/proofs.js +185 -47
- package/dist/adapters/utxo/proofs.js.map +1 -1
- package/dist/adapters/utxo/rawblock.d.ts +46 -0
- package/dist/adapters/utxo/rawblock.js +159 -0
- package/dist/adapters/utxo/rawblock.js.map +1 -0
- package/dist/adapters/utxo/rawtx.d.ts +14 -0
- package/dist/adapters/utxo/rawtx.js +44 -14
- package/dist/adapters/utxo/rawtx.js.map +1 -1
- package/dist/core/blockchain/handle.d.ts +6 -27
- package/dist/core/blockchain/handle.js +112 -112
- package/dist/core/blockchain/handle.js.map +1 -1
- package/dist/core/config/types.d.ts +15 -0
- package/dist/core/config/types.js.map +1 -1
- package/dist/core/container/container.d.ts +1 -8
- package/dist/core/container/container.js +42 -8
- package/dist/core/container/container.js.map +1 -1
- package/dist/core/driver/types.d.ts +34 -1
- package/dist/core/driver/types.js.map +1 -1
- package/dist/core/errors/codes.d.ts +10 -0
- package/dist/core/errors/codes.js +4 -0
- package/dist/core/errors/codes.js.map +1 -1
- package/dist/core/lifecycle/engine-rules.d.ts +3 -4
- package/dist/core/lifecycle/engine-rules.js +16 -6
- package/dist/core/lifecycle/engine-rules.js.map +1 -1
- package/dist/core/lifecycle/engine.d.ts +2 -0
- package/dist/core/lifecycle/engine.js +19 -1
- package/dist/core/lifecycle/engine.js.map +1 -1
- package/dist/core/lifecycle/evaluate.js +9 -4
- package/dist/core/lifecycle/evaluate.js.map +1 -1
- package/dist/core/lifecycle/monitor.js +16 -6
- package/dist/core/lifecycle/monitor.js.map +1 -1
- package/dist/core/lifecycle/reconcile.d.ts +1 -1
- package/dist/core/lifecycle/reconcile.js +1 -1
- package/dist/core/lifecycle/reconcile.js.map +1 -1
- package/dist/core/lifecycle/workers.d.ts +9 -3
- package/dist/core/lifecycle/workers.js +32 -14
- package/dist/core/lifecycle/workers.js.map +1 -1
- package/dist/core/model/ids.d.ts +1 -0
- package/dist/core/model/ids.js +1 -0
- package/dist/core/model/ids.js.map +1 -1
- package/dist/core/model/ordering.d.ts +8 -0
- package/dist/core/model/ordering.js.map +1 -1
- package/dist/core/model/transaction.d.ts +7 -0
- package/dist/core/model/transaction.js.map +1 -1
- package/dist/core/observe/scanner.js +3 -0
- package/dist/core/observe/scanner.js.map +1 -1
- package/dist/core/signing/wallet.js +8 -0
- package/dist/core/signing/wallet.js.map +1 -1
- package/dist/core/store/format.d.ts +20 -0
- package/dist/core/store/format.js +86 -0
- package/dist/core/store/format.js.map +1 -0
- package/dist/core/store/memory.js +2 -2
- package/dist/core/store/memory.js.map +1 -1
- package/dist/core/store/types.d.ts +15 -3
- package/dist/core/store/types.js +2 -0
- package/dist/core/store/types.js.map +1 -1
- package/dist/core/transport/http-transport.js +21 -13
- package/dist/core/transport/http-transport.js.map +1 -1
- package/dist/core/transport/types.d.ts +16 -1
- package/dist/core/transport/types.js.map +1 -1
- package/dist/core/util/json.d.ts +7 -1
- package/dist/core/util/json.js +13 -4
- package/dist/core/util/json.js.map +1 -1
- package/dist/core/util/names.d.ts +6 -0
- package/dist/core/util/names.js +10 -0
- package/dist/core/util/names.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/testing/contracts/operations.js +20 -1
- package/dist/testing/contracts/operations.js.map +1 -1
- package/dist/testing/env.d.ts +5 -0
- package/dist/testing/env.js +1 -1
- package/dist/testing/env.js.map +1 -1
- package/dist/testing/faulty-store.d.ts +2 -0
- package/dist/testing/faulty-store.js +5 -0
- package/dist/testing/faulty-store.js.map +1 -1
- package/package.json +17 -7
package/CHANGELOG.md
CHANGED
|
@@ -7,11 +7,161 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.2.0] - 2026-10-21
|
|
11
|
+
|
|
12
|
+
crypto-aio 0.2.0 settles everything 1.0 will promise: the API is locked by reports in CI,
|
|
13
|
+
the driver port is final, stored Operations carry a record format, and the gaps that could
|
|
14
|
+
make a paid transfer look failed are closed. Entries marked **Breaking** need a change from
|
|
15
|
+
some users; [Upgrade to 1.0](https://vhidvz.github.io/crypto-aio/reference/upgrading.html)
|
|
16
|
+
says what to do for each.
|
|
17
|
+
|
|
18
|
+
### Added
|
|
19
|
+
|
|
20
|
+
- `SECURITY.md`: how to report a vulnerability privately, and what is in scope.
|
|
21
|
+
- Operation records carry `format` (`OPERATION_FORMAT`, 1), the record format they were
|
|
22
|
+
stored in; a record without one (0.1.0) reads as format 1. A process never reads a record
|
|
23
|
+
of a newer format: the read throws the new `RECORD_FORMAT_UNSUPPORTED`, and a worker
|
|
24
|
+
releases its claim for a newer process. The `OperationStore` contract suite checks that
|
|
25
|
+
a store keeps `format`, and tests pin the intent hash and the store keys as 0.1.0 wrote
|
|
26
|
+
them.
|
|
27
|
+
- API reports (`etc/api/*.api.md`, one per entry point), generated by API Extractor: CI fails
|
|
28
|
+
when the public API changes without its report (`pnpm api:update`).
|
|
29
|
+
- Release tooling: a tag such as `1.0.0-rc.1` publishes under npm's `next` dist-tag, a
|
|
30
|
+
release tag must match `package.json` and have a `CHANGELOG.md` section, which becomes the
|
|
31
|
+
GitHub Release's notes, and a release runs every CI check before it publishes.
|
|
32
|
+
- CI runs on Node.js 22.12.0, 22, 24 and 26, audits the runtime dependencies, and checks the
|
|
33
|
+
package's exports and types with `publint` and `@arethetypeswrong/cli`
|
|
34
|
+
(`pnpm lint:package`). CodeQL and Dependabot are configured.
|
|
35
|
+
|
|
36
|
+
### Changed
|
|
37
|
+
|
|
38
|
+
- **Breaking:** crypto-aio needs Node.js 22.12 or later (`engines.node` is `>=22.12`), the
|
|
39
|
+
version every family already needed for Solana. `engines` no longer names an npm version,
|
|
40
|
+
so npm 11 installs without an engine warning.
|
|
41
|
+
- `package.json` declares `"type": "commonjs"`.
|
|
42
|
+
- **Breaking:** a transfer whose transaction executed but shows no transfer to the
|
|
43
|
+
recipient fails with the new `TX_UNEVIDENCED`, not `TX_REVERTED`: an EVM or Tron token
|
|
44
|
+
that logged no `Transfer` to the recipient, or TON jettons sent to a wallet the master
|
|
45
|
+
does not name. Value may have moved, so check the chain before paying again; a
|
|
46
|
+
`TX_REVERTED` now always means the execution failed. Drivers say which with
|
|
47
|
+
`failure: 'reverted' | 'unevidenced'` (`TxFailure`) on `observe` and `includedFinal`, and
|
|
48
|
+
the core keeps it on the Attempt's observation (`failure`, a field stores must keep).
|
|
49
|
+
- **Breaking:** an endpoint reads `healthy` in `status()` and `getNetworkStatus()` only
|
|
50
|
+
once its height is known, when its family probes heights: before that it is `unknown`,
|
|
51
|
+
where a confirmed identity alone used to make it `healthy`.
|
|
52
|
+
- **Breaking:** a proof needs `proofQuorum` endpoints even after some drop out of its count
|
|
53
|
+
(down for three health intervals): the quorum is capped by the endpoints configured, not
|
|
54
|
+
by those still counted, so the one endpoint left never proves alone; proofs wait for the
|
|
55
|
+
others instead. The new `transport.degradedProofs: true` restores the old behavior, which
|
|
56
|
+
favours liveness.
|
|
57
|
+
- `lifecycle.leaseWaitMs` (default: `leaseMs`): how long a transfer waits for its wallet's
|
|
58
|
+
address lease before `SEQUENCE_BUSY`, so transfers can queue behind a slow signer.
|
|
59
|
+
- Fuzz tests feed every decoder of untrusted bytes (Solana messages and transactions, Tron
|
|
60
|
+
protobuf, Bitcoin and EVM raw transactions, Avalanche transactions, cb58, exact-integer
|
|
61
|
+
JSON) random and mutated input; they may refuse it, never throw an unclassified error.
|
|
62
|
+
A nightly workflow runs them deeper, runs the live read-only integration suites, and
|
|
63
|
+
runs the unit suites on the newest release of every SDK.
|
|
64
|
+
- The pack check compiles a project that imports every entry point with TypeScript 5.3 (the
|
|
65
|
+
oldest supported, with `skipLibCheck`), the tested 5.9 and 7, under `nodenext` and
|
|
66
|
+
`bundler` resolution.
|
|
67
|
+
- `@solana/web3.js` 3 is supported next to 1.99 (peer range `^1.99.0 || ^3.0.0`). The
|
|
68
|
+
Solana driver now compiles its messages and derives token account addresses itself
|
|
69
|
+
(checked byte for byte against the SDK), so signed bytes no longer depend on the SDK
|
|
70
|
+
version; the SDK only backs `native()`. The pack check loads the family with 3.x too.
|
|
71
|
+
- `BuildContext.decimals`: the decimals the core scaled a transfer's amounts with. The
|
|
72
|
+
Solana driver refuses a token transfer whose mint has other decimals
|
|
73
|
+
(`ASSET_RESOLUTION`), which a wrong registration would otherwise sign as a mis-scaled
|
|
74
|
+
`transferChecked`.
|
|
75
|
+
- `ReplacementPolicy.comparePrice` (optional): the EVM family ranks earlier cancels by
|
|
76
|
+
price, so a repeat cancel climbs from the highest one without an explicit `fee`.
|
|
77
|
+
- `assets` on the root container's options registers tokens (decimals, symbol, aliases)
|
|
78
|
+
without writing a plugin.
|
|
79
|
+
- `PROVIDER_MISCONFIGURED` for refused credentials carries `details.httpStatus` (401 or 403).
|
|
80
|
+
- Solana: the signature fee is computed (5,000 lamports per signature), and an endpoint's
|
|
81
|
+
`getFeeForMessage` quote must match the message's fee exactly; any other quote fails the
|
|
82
|
+
estimate with a retryable `PROVIDER_UNAVAILABLE`, so one endpoint can neither inflate an
|
|
83
|
+
estimate (refusing a payable transfer) nor deflate it. Whether an explicit fee fits in
|
|
84
|
+
u64 is decided locally.
|
|
85
|
+
- **Breaking:** Bitcoin: a wallet whose signer does not declare the scheme its address type
|
|
86
|
+
signs with (a `p2tr` wallet on an ECDSA-only signer, such as a KMS key) is refused with
|
|
87
|
+
`CONFIG_INVALID` when the wallet resolves (`ready()`, `walletAddress()`, `transfer()`,
|
|
88
|
+
`prepareTransfer()`), before anything is built or reserved, instead of failing at
|
|
89
|
+
signing. A Schnorr-only signer on a non-`p2tr` wallet gets the same error, where it got
|
|
90
|
+
`INVALID_ADDRESS`. Watch-only wallets are unaffected. Drivers declare this with the
|
|
91
|
+
optional `ChainDriver.signingSchemes(wallet)`.
|
|
92
|
+
- **Breaking:** EVM and Tron: a token whose contract answers `deprecated()` with `true`
|
|
93
|
+
(Tether's `TetherToken`, USDT on Ethereum and Tron) is refused before signing with
|
|
94
|
+
`ASSET_RESOLUTION`, rather than sent through a contract that forwards it and logs no
|
|
95
|
+
`Transfer`. Every token estimate makes one more read.
|
|
96
|
+
- **Breaking:** EVM: the `maxGasLimit` option (`chains.<id>.options`, a handle's `options`,
|
|
97
|
+
or a network's `params.maxGasLimit`) bounds the gas limit of every transfer, replacement
|
|
98
|
+
and cancel, by default 2^24 (`DEFAULT_MAX_GAS_LIMIT`, Ethereum's EIP-7825 cap). An
|
|
99
|
+
estimate (with its headroom) or an override above it fails with `INVALID_INTENT` before
|
|
100
|
+
signing (`details.required`, `details.maxGasLimit`).
|
|
101
|
+
- EVM: on OP Stack chains since Isthmus, the operator fee (`GasPriceOracle.getOperatorFee`
|
|
102
|
+
for the gas limit) is its own `operator` charge and `details.operatorFee`, counted in
|
|
103
|
+
`details.expected` and the funds check.
|
|
104
|
+
- **Breaking:** the Bitcoin scanner reads each block's own bytes (`/block/:hash/raw`) and
|
|
105
|
+
delivers only transactions its header commits to: the merkle root (refusing the
|
|
106
|
+
CVE-2012-2459 duplicate), a coinbase first, and the BIP141 witness commitment; the header
|
|
107
|
+
read at the height must match those bytes. A scanned transaction's `from`, input values and
|
|
108
|
+
fee come from the previous transactions' bytes, checked against the txids its inputs name.
|
|
109
|
+
A block that does not match is a retryable `PROVIDER_INCONSISTENT` and decides nothing. A
|
|
110
|
+
filtered scan uses the indexer's JSON pages only to find spends from watched addresses,
|
|
111
|
+
checked against the bytes; an unfiltered one reads one previous transaction per distinct
|
|
112
|
+
parent outside the block, so scan with `filter.addresses`. `details.vout[].type` is named
|
|
113
|
+
from the script, as Blockstream electrs names it.
|
|
114
|
+
- The transport's `http` reads a binary answer with `responseType: 'bytes'`, within
|
|
115
|
+
`maxResponseBytes`.
|
|
116
|
+
- A reference PostgreSQL implementation of the four store ports, in
|
|
117
|
+
`examples/postgres-store` (schema, source, README; not part of the package), passes every
|
|
118
|
+
store contract suite and an engine crash-and-recover run against PostgreSQL 16 in CI.
|
|
119
|
+
- `pnpm test:evm-local` proves the EVM write path on a local anvil node, with ethers and
|
|
120
|
+
web3: proven finality, idempotent repeats, concurrent nonces, an ERC-20, replace, cancel,
|
|
121
|
+
crash recovery, funds checks and a reorg. CI runs it on every change.
|
|
122
|
+
- **Breaking:** an idempotency key and a scanner's `cursorKey` must be well-formed text
|
|
123
|
+
without U+0000 (`INVALID_INTENT`, `CONFIG_INVALID`): a database may refuse U+0000, and a
|
|
124
|
+
driver may turn a lone surrogate into U+FFFD, so two keys would become one.
|
|
125
|
+
- The store ports say which clock stamps times (the container's, or a wall clock the
|
|
126
|
+
processes share), and that a store may refuse an attempt id another Operation holds; the
|
|
127
|
+
contract suite no longer reuses one. `createFakeEnv` takes a `clock`, so stores built
|
|
128
|
+
beforehand can share it, and `FaultyOperationStore` passes `purge` through. The memory
|
|
129
|
+
store lists and purges nothing for a negative `limit`, as for 0.
|
|
130
|
+
- `RecoveryReport.unresent`: a `signed` or ambiguous Operation whose wallet no longer
|
|
131
|
+
resolves is now checked on chain and counted `unresent`, where it was counted `failed`
|
|
132
|
+
without its check.
|
|
133
|
+
- **Breaking (types only):** `Blockchain`'s constructor is private (handles come from
|
|
134
|
+
`aio.blockchain()` or `Blockchain.create()`), and its internal `protected` methods are gone
|
|
135
|
+
from the type declarations. `CryptoAio`'s constructor has one signature, `(options?)`.
|
|
136
|
+
|
|
137
|
+
### Deprecated
|
|
138
|
+
|
|
139
|
+
- `library: 'web3'` (and `Library.WEB3`): web3.js is no longer maintained upstream (4.16.0 is
|
|
140
|
+
its last release). It keeps working through 1.x, warns once per process with a
|
|
141
|
+
`DeprecationWarning` (code `CRYPTO_AIO_WEB3`), and is removed in 2.0. Use `ethers`.
|
|
142
|
+
|
|
143
|
+
### Fixed
|
|
144
|
+
|
|
145
|
+
- `evmChainPlugin` registers each `assets` ERC-20 under its EIP-55 checksummed contract,
|
|
146
|
+
whatever case it is given in, so a token's alias, its ref, its transfers and its balances
|
|
147
|
+
share one asset id (a lower-case contract made two assets, and deposits missed the
|
|
148
|
+
alias's). A token of another standard, a malformed contract, or a mixed-case contract with
|
|
149
|
+
a wrong checksum is refused with `CONFIG_INVALID` at registration.
|
|
150
|
+
- `stringifyTagged` encodes a Node.js `Buffer` as bytes, as the memory store keeps it; it was
|
|
151
|
+
written as `{ type: 'Buffer', data }` and read back as a plain object by a durable store.
|
|
152
|
+
- TON: `transfer bounced` and `jetton transfer bounced` no longer rest on the indexer's
|
|
153
|
+
word. The provider's raw records of the wallet transaction and of each delivery, checked
|
|
154
|
+
against their hashes and linked by message hash, must show the bounce; until they do, or
|
|
155
|
+
while the provider's endpoints disagree, the transfer stays undecided (a warning with code
|
|
156
|
+
`BOUNCE_UNPROVEN` when they contradict the indexer). A lone lying indexer can delay a
|
|
157
|
+
verdict, never fail a transfer that landed.
|
|
158
|
+
|
|
10
159
|
## [0.1.0] - 2026-10-01
|
|
11
160
|
|
|
12
161
|
### Added
|
|
13
162
|
|
|
14
163
|
- initial release 🎉🎊.
|
|
15
164
|
|
|
16
|
-
[Unreleased]: https://github.com/vhidvz/crypto-aio/compare/0.
|
|
165
|
+
[Unreleased]: https://github.com/vhidvz/crypto-aio/compare/0.2.0...HEAD
|
|
166
|
+
[0.2.0]: https://github.com/vhidvz/crypto-aio/compare/0.1.0...0.2.0
|
|
17
167
|
[0.1.0]: https://github.com/vhidvz/crypto-aio/releases/tag/0.1.0
|
package/README.md
CHANGED
|
@@ -1,11 +1,20 @@
|
|
|
1
|
-
|
|
1
|
+
<h1 align="center">
|
|
2
|
+
<a href="https://vhidvz.github.io/crypto-aio/">
|
|
3
|
+
<picture>
|
|
4
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/vhidvz/crypto-aio/main/docs/public/crypto-aio-logo-dark.svg">
|
|
5
|
+
<img alt="crypto-aio" src="https://raw.githubusercontent.com/vhidvz/crypto-aio/main/docs/public/crypto-aio-logo.svg" width="420">
|
|
6
|
+
</picture>
|
|
7
|
+
</a>
|
|
8
|
+
</h1>
|
|
9
|
+
|
|
10
|
+
<div align="center">
|
|
2
11
|
|
|
3
12
|
[](https://www.npmjs.com/package/crypto-aio)
|
|
4
13
|
[](https://github.com/vhidvz/crypto-aio/actions/workflows/ci.yml)
|
|
5
14
|

|
|
6
15
|
[](https://htmlpreview.github.io/?https://github.com/vhidvz/crypto-aio/blob/main/coverage/lcov-report/index.html)
|
|
7
16
|
[](LICENSE)
|
|
8
|
-
[](https://vhidvz.github.io/crypto-aio/)
|
|
9
18
|
|
|
10
19
|
**One TypeScript API for moving money on blockchains.** Balances, transfers, confirmations
|
|
11
20
|
and deposit scanning across EVM chains, Bitcoin, Tron, Solana, TON and the Avalanche X-Chain and
|
|
@@ -17,6 +26,8 @@ P-Chain, built for exchanges, wallets and payment systems.
|
|
|
17
26
|
[Examples](https://vhidvz.github.io/crypto-aio/build/examples.html) ·
|
|
18
27
|
[API](https://vhidvz.github.io/crypto-aio/reference/api.html)
|
|
19
28
|
|
|
29
|
+
</div>
|
|
30
|
+
|
|
20
31
|
## Why crypto-aio
|
|
21
32
|
|
|
22
33
|
Every chain has an SDK that can build, sign and send a transaction. None of them is a payment
|
|
@@ -46,10 +57,10 @@ principles, starting with [what a ledger is](https://vhidvz.github.io/crypto-aio
|
|
|
46
57
|
|
|
47
58
|
| Family | Chains | Through |
|
|
48
59
|
| --- | --- | --- |
|
|
49
|
-
| EVM | Ethereum, BNB Smart Chain, Polygon, Avalanche C-Chain, Arbitrum, Optimism, Base, and any EVM chain you add | `ethers` 6 (
|
|
60
|
+
| EVM | Ethereum, BNB Smart Chain, Polygon, Avalanche C-Chain, Arbitrum, Optimism, Base, and any EVM chain you add | `ethers` 6 (or the deprecated `web3` 4) |
|
|
50
61
|
| Bitcoin | mainnet, testnet, testnet4, signet, regtest | `bitcoinjs-lib` 7 and an Esplora indexer |
|
|
51
62
|
| Tron | mainnet, Shasta, Nile | `tronweb` 6 |
|
|
52
|
-
| Solana | mainnet, devnet, testnet | `@solana/web3.js` 1 |
|
|
63
|
+
| Solana | mainnet, devnet, testnet | `@solana/web3.js` 1 or 3 |
|
|
53
64
|
| TON | mainnet, testnet | `@ton/ton` 16 and toncenter |
|
|
54
65
|
| Avalanche X-Chain and P-Chain | mainnet, Fuji | `@avalabs/avalanchejs` 5 and the Avalanche Data API |
|
|
55
66
|
|
|
@@ -58,11 +69,11 @@ What each network supports, family by family, is in
|
|
|
58
69
|
|
|
59
70
|
## Install
|
|
60
71
|
|
|
61
|
-
crypto-aio needs Node.js 22
|
|
72
|
+
crypto-aio needs Node.js 22.12 or later. Install the package, and only the
|
|
62
73
|
SDK of each family you use:
|
|
63
74
|
|
|
64
75
|
```sh
|
|
65
|
-
npm install crypto-aio ethers # EVM chains
|
|
76
|
+
npm install crypto-aio ethers # EVM chains
|
|
66
77
|
npm install crypto-aio bitcoinjs-lib # Bitcoin
|
|
67
78
|
npm install crypto-aio tronweb # Tron
|
|
68
79
|
npm install crypto-aio @solana/web3.js # Solana
|
|
@@ -71,6 +82,9 @@ npm install crypto-aio @avalabs/avalanchejs # Avalanche X-Chain and P-Chain
|
|
|
71
82
|
```
|
|
72
83
|
|
|
73
84
|
A handle whose SDK is missing fails with `DEPENDENCY_MISSING` and names the install command.
|
|
85
|
+
The type declarations need TypeScript 5.3 or later, and each family's entry point
|
|
86
|
+
(`crypto-aio/evm`, …) the types of its SDK; some SDKs' own declarations need TypeScript 5.7
|
|
87
|
+
unless `skipLibCheck` is on. TypeScript 7 is supported.
|
|
74
88
|
|
|
75
89
|
## Your first transfer, with no network and no keys
|
|
76
90
|
|
|
@@ -137,16 +151,22 @@ family.
|
|
|
137
151
|
|
|
138
152
|
## Status
|
|
139
153
|
|
|
140
|
-
crypto-aio is at **0.
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
154
|
+
crypto-aio is at **0.2.0**, on its way to 1.0, from which [semantic
|
|
155
|
+
versioning](https://vhidvz.github.io/crypto-aio/reference/stability.html) covers the whole API,
|
|
156
|
+
the driver port and what a process stores; the 0.0.x releases on npm are an older, unrelated
|
|
157
|
+
API. [Known limitations](https://vhidvz.github.io/crypto-aio/reference/limitations.html) lists
|
|
158
|
+
what it does not do yet, and [Upgrade to 1.0](https://vhidvz.github.io/crypto-aio/reference/upgrading.html)
|
|
159
|
+
what changes from 0.1.0. Only in-memory stores ship: production needs durable stores of your
|
|
160
|
+
own, proven with the contract suites in `crypto-aio/testing`; [examples/postgres-store](examples/postgres-store)
|
|
161
|
+
is a reference implementation on PostgreSQL. Release notes are in the [changelog](CHANGELOG.md).
|
|
145
162
|
|
|
146
163
|
## Contributing
|
|
147
164
|
|
|
148
165
|
Issues and pull requests are welcome. `pnpm install` and `pnpm check` (lint, typecheck and tests)
|
|
149
|
-
are all a change needs locally
|
|
166
|
+
are all a change needs locally, plus `pnpm api:update` when it changes the public API (CI
|
|
167
|
+
compares the API with the reports in `etc/api/`). `pnpm test:evm-local` also signs, broadcasts
|
|
168
|
+
and proves real EVM transactions on a local anvil node, which it starts and stops; CI runs it
|
|
169
|
+
on every change. The [source map](https://vhidvz.github.io/crypto-aio/explore/source-map.html)
|
|
150
170
|
explains the repository, and [docs/README.md](docs/README.md) how the documentation is built and
|
|
151
171
|
tested.
|
|
152
172
|
|
|
@@ -98,8 +98,10 @@ async function priceFor(ctx, fee, signal) {
|
|
|
98
98
|
const { client, config } = ctx;
|
|
99
99
|
if (typeof fee === 'object') {
|
|
100
100
|
const { params, gasLimit } = (0, fees_1.parseFeeOverride)(fee, config.feeModel);
|
|
101
|
-
// An explicit fee above
|
|
101
|
+
// An explicit fee above either bound is refused before any request.
|
|
102
102
|
(0, fees_1.assertWithinCeiling)(params, config.maxFeePerGas);
|
|
103
|
+
if (gasLimit !== undefined)
|
|
104
|
+
(0, fees_1.assertWithinGasLimit)(gasLimit, config.maxGasLimit);
|
|
103
105
|
return { speed: 'custom', params, ...(gasLimit !== undefined ? { gasLimit } : {}) };
|
|
104
106
|
}
|
|
105
107
|
// A node's suggestion is clamped to the ceiling, so no endpoint can raise it.
|
|
@@ -128,13 +130,59 @@ async function l1FeeFor(ctx, fields, signal) {
|
|
|
128
130
|
throw new error_1.ProviderError('PROVIDER_UNAVAILABLE', 'the L1 fee oracle gave no fee');
|
|
129
131
|
}
|
|
130
132
|
}
|
|
133
|
+
/**
|
|
134
|
+
* OP Stack since Isthmus: the oracle's operator fee (`getOperatorFee`) for the whole gas
|
|
135
|
+
* limit. The fee grows with the gas used, so the limit gives an upper bound at the chain's
|
|
136
|
+
* current operator settings, as the `network` charge does at the fee cap; the predeploy
|
|
137
|
+
* applies the formula of the chain's fork (Isthmus or Jovian). `undefined` where nothing
|
|
138
|
+
* is charged: a zero fee, or a predeploy that has no such method yet (a revert, or `0x`).
|
|
139
|
+
* A node error is retryable (`callIfPresent`), and a malformed answer is a retryable
|
|
140
|
+
* `PROVIDER_UNAVAILABLE`, never no fee.
|
|
141
|
+
*/
|
|
142
|
+
async function operatorFeeFor(ctx, gasLimit, signal) {
|
|
143
|
+
if (!ctx.config.l1DataFee)
|
|
144
|
+
return undefined;
|
|
145
|
+
const { client } = ctx;
|
|
146
|
+
const result = await (0, reader_1.callIfPresent)(client, { to: network_1.GAS_PRICE_ORACLE, data: client.abi.encodeGetOperatorFee(gasLimit) }, (0, reader_1.withSignal)(reader_1.READ, signal));
|
|
147
|
+
if (result === null || result === '0x')
|
|
148
|
+
return undefined;
|
|
149
|
+
let fee;
|
|
150
|
+
try {
|
|
151
|
+
fee = client.abi.decodeUint256(result);
|
|
152
|
+
}
|
|
153
|
+
catch {
|
|
154
|
+
throw new error_1.ProviderError('PROVIDER_UNAVAILABLE', 'the operator fee oracle gave no fee');
|
|
155
|
+
}
|
|
156
|
+
return fee === 0n ? undefined : fee;
|
|
157
|
+
}
|
|
158
|
+
/** The fee draft for `fields`, with the OP Stack charges read side by side. */
|
|
131
159
|
async function draftFor(ctx, fields, price, signal) {
|
|
132
|
-
const l1Fee = await
|
|
160
|
+
const [l1Fee, operatorFee] = await Promise.all([
|
|
161
|
+
l1FeeFor(ctx, fields, signal),
|
|
162
|
+
operatorFeeFor(ctx, fields.gasLimit, signal),
|
|
163
|
+
]);
|
|
133
164
|
return (0, fees_1.feeDraft)(price.speed, fields.gasLimit, price.params, {
|
|
134
165
|
...(price.baseFeePerGas !== undefined ? { baseFeePerGas: price.baseFeePerGas } : {}),
|
|
135
166
|
...(l1Fee !== undefined ? { l1Fee } : {}),
|
|
167
|
+
...(operatorFee !== undefined ? { operatorFee } : {}),
|
|
136
168
|
});
|
|
137
169
|
}
|
|
170
|
+
/**
|
|
171
|
+
* Refuses a transfer of a token whose contract says it is deprecated. Tether's
|
|
172
|
+
* `TetherToken` (USDT on Ethereum) forwards a deprecated contract's `transfer` to its
|
|
173
|
+
* upgraded contract, which moves the value and emits the `Transfer` event, so the transfer
|
|
174
|
+
* estimates and executes, and the verdict, which reads the old contract's event, finds no
|
|
175
|
+
* evidence of it. Read once per estimate, before `eth_estimateGas` (which such a transfer
|
|
176
|
+
* passes); the core estimates before every build. One endpoint's answer, as for the
|
|
177
|
+
* builder's other token reads, not the proof quorum's: a `true` can only refuse before
|
|
178
|
+
* signing, the safe direction (as one endpoint's revert in `eth_estimateGas` already
|
|
179
|
+
* does), and a wrong `false` leaves the transfer where it was without the guard.
|
|
180
|
+
*/
|
|
181
|
+
async function refuseDeprecated(ctx, token, signal) {
|
|
182
|
+
if (await (0, reader_1.erc20Deprecated)(ctx.client, token, (0, reader_1.withSignal)(reader_1.READ, signal))) {
|
|
183
|
+
throw new error_1.ValidationError('ASSET_RESOLUTION', 'the token contract is deprecated in favour of an upgraded contract; the asset must be re-registered at the upgraded contract');
|
|
184
|
+
}
|
|
185
|
+
}
|
|
138
186
|
/** geth's estimate reached its gas cap: the call fails at any gas limit. */
|
|
139
187
|
const GAS_ALLOWANCE = /^gas required exceeds allowance/i;
|
|
140
188
|
/**
|
|
@@ -177,8 +225,13 @@ function createEvmBuilder(ctx) {
|
|
|
177
225
|
async estimateFee(intent, build) {
|
|
178
226
|
const transfer = transferOf(intent);
|
|
179
227
|
const price = await priceFor(ctx, intent.fee, build.signal);
|
|
228
|
+
if (transfer.token !== undefined) {
|
|
229
|
+
await refuseDeprecated(ctx, transfer.token, build.signal);
|
|
230
|
+
}
|
|
180
231
|
const gasLimit = price.gasLimit ??
|
|
181
232
|
(0, fees_1.gasLimitFrom)(await estimateGas(ctx, intent.from, transfer, build.signal));
|
|
233
|
+
// The estimate with its headroom is what would be signed, so that is what is bounded.
|
|
234
|
+
(0, fees_1.assertWithinGasLimit)(gasLimit, ctx.config.maxGasLimit);
|
|
182
235
|
const nonce = build.ordering?.kind === 'nonce' ? build.ordering.nonce : 0n;
|
|
183
236
|
const fields = fieldsOf(ctx, callOf(client, transfer), nonce, gasLimit, price.params);
|
|
184
237
|
return draftFor(ctx, fields, price, build.signal);
|
|
@@ -210,8 +263,9 @@ function createEvmBuilder(ctx) {
|
|
|
210
263
|
if (model !== ctx.config.feeModel) {
|
|
211
264
|
throw new error_1.ValidationError('INVALID_INTENT', `this network takes ${ctx.config.feeModel} fees`);
|
|
212
265
|
}
|
|
213
|
-
// The
|
|
266
|
+
// The bounds are checked again, whatever produced the fee object.
|
|
214
267
|
(0, fees_1.assertWithinCeiling)(params, ctx.config.maxFeePerGas);
|
|
268
|
+
(0, fees_1.assertWithinGasLimit)(gasLimit, ctx.config.maxGasLimit);
|
|
215
269
|
const fields = fieldsOf(ctx, callOf(client, transfer), nonceOf(build.ordering), gasLimit, params);
|
|
216
270
|
return unsignedTx(ctx, fields, fee, keyOf(build.keys), {
|
|
217
271
|
asset: (0, asset_1.assetId)(ctx.chain.id, ctx.network.id, intent.asset),
|
|
@@ -296,13 +350,17 @@ function createEvmReplacement(ctx) {
|
|
|
296
350
|
return {
|
|
297
351
|
replace: config.capabilities.has('replace-fee'),
|
|
298
352
|
cancel: config.capabilities.has('cancel'),
|
|
353
|
+
comparePrice: (a, b) => (0, fees_1.comparePrices)((0, fees_1.feeOf)(a.fee.details).params, (0, fees_1.feeOf)(b.fee.details).params),
|
|
299
354
|
async buildReplacement(previous, fee, build) {
|
|
300
355
|
const before = (0, fees_1.feeOf)(previous.fee.details);
|
|
301
356
|
const price = await priceFor(ctx, fee, build.signal);
|
|
302
357
|
if (!(0, fees_1.meetsBump)(before.params, price.params, bump))
|
|
303
358
|
throw tooLow('a replacement');
|
|
304
359
|
const old = unsignedFields(ctx, previous);
|
|
305
|
-
|
|
360
|
+
// The original's gas limit too: no replacement signs one above the bound.
|
|
361
|
+
const gasLimit = price.gasLimit ?? before.gasLimit;
|
|
362
|
+
(0, fees_1.assertWithinGasLimit)(gasLimit, config.maxGasLimit);
|
|
363
|
+
const fields = fieldsOf(ctx, { to: old.to, value: old.value, data: old.data }, old.nonce, gasLimit, price.params);
|
|
306
364
|
return unsignedTx(ctx, fields, await draftFor(ctx, fields, price, build.signal), keyFrom(previous), previous.summary);
|
|
307
365
|
},
|
|
308
366
|
async buildCancel(previous, build, fee) {
|
|
@@ -315,6 +373,8 @@ function createEvmReplacement(ctx) {
|
|
|
315
373
|
// A cancel whose least bump would pay above the ceiling is refused.
|
|
316
374
|
(0, fees_1.assertWithinCeiling)(price.params, config.maxFeePerGas);
|
|
317
375
|
const nonce = nonceOf(previous.ordering);
|
|
376
|
+
// A self-transfer needs 21,000 gas, which every bound allows; an explicit fee's
|
|
377
|
+
// `gasLimit` was bounded when it was parsed.
|
|
318
378
|
const fields = fieldsOf(ctx, { to: build.from, value: 0n, data: '0x' }, nonce, price.gasLimit ?? fees_1.TRANSFER_GAS, price.params);
|
|
319
379
|
return unsignedTx(ctx, fields, await draftFor(ctx, fields, price, build.signal), keyFrom(previous), {
|
|
320
380
|
asset: (0, asset_1.assetId)(ctx.chain.id, ctx.network.id, 'native'),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"builder.js","sourceRoot":"","sources":["../../../src/adapters/evm/builder.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Fees, funds, building, assembling, broadcasting, and same-nonce replace and cancel.\n * One output per transfer, native or ERC-20 `transfer`.\n */\nimport type {\n BroadcastResult,\n Broadcaster,\n BuildContext,\n ReplacementPolicy,\n TxBuilder,\n WalletKey,\n} from '../../core/driver/types';\nimport {\n ChainError,\n ProviderError,\n SigningError,\n StateError,\n UnsupportedCapabilityError,\n ValidationError,\n isCryptoAioError,\n} from '../../core/errors/error';\nimport { assetId, parseAssetId } from '../../core/model/asset';\nimport type { FeeEstimateDraft, FeeOverride, FeeSpeed } from '../../core/model/fee';\nimport type { DriverIntent, IntentSummary } from '../../core/model/intent';\nimport type { OrderingData } from '../../core/model/ordering';\nimport type { UnsignedTx } from '../../core/model/transaction';\nimport { equalBytes, fromHex, toHex } from '../../core/util/bytes';\nimport { classifyOwnBroadcast } from './errors';\nimport {\n FEE_HISTORY_BLOCKS,\n FEE_PERCENTILES,\n TRANSFER_GAS,\n assertWithinCeiling,\n capPrice,\n feeDraft,\n feeOf,\n feesFromHistory,\n gasLimitFrom,\n legacyPrice,\n meetsBump,\n minimumBump,\n parseFeeOverride,\n type EvmFeeParams,\n} from './fees';\nimport { GAS_PRICE_ORACLE } from './network';\nimport {\n READ,\n erc20Balance,\n isExecutionFailure,\n isRevert,\n withSignal,\n type EvmContext,\n} from './reader';\nimport type { EvmClient, EvmTxFields } from './types';\n\n/** One transfer: `token` is the ERC-20 contract, absent for the native asset. */\ninterface Transfer {\n readonly to: string;\n readonly amount: bigint;\n readonly token?: string;\n}\n\ninterface Price {\n readonly speed: FeeSpeed | 'custom';\n readonly params: EvmFeeParams;\n readonly baseFeePerGas?: bigint;\n readonly gasLimit?: bigint;\n}\n\nfunction transferOf(intent: DriverIntent): Transfer {\n if (intent.memo !== undefined) {\n throw new UnsupportedCapabilityError(\n 'UNSUPPORTED_CAPABILITY',\n 'EVM transfers carry no memo',\n );\n }\n const [output] = intent.outputs;\n if (!output || intent.outputs.length !== 1) {\n throw new ValidationError('INVALID_INTENT', 'an EVM transfer has exactly one output');\n }\n if (intent.asset === 'native') return { to: output.to, amount: output.amount };\n if (intent.asset.standard !== 'erc20') {\n throw new ValidationError('ASSET_RESOLUTION', `EVM tokens use the 'erc20' standard`);\n }\n return { to: output.to, amount: output.amount, token: intent.asset.contract };\n}\n\n/** The call a transfer makes: a value transfer, or `transfer(to, amount)` on the token. */\nfunction callOf(\n client: EvmClient,\n transfer: Transfer,\n): { to: string; value: bigint; data: string } {\n return transfer.token === undefined\n ? { to: transfer.to, value: transfer.amount, data: '0x' }\n : {\n to: transfer.token,\n value: 0n,\n data: client.abi.encodeTransfer(transfer.to, transfer.amount),\n };\n}\n\nfunction fieldsOf(\n ctx: EvmContext,\n call: { to: string; value: bigint; data: string },\n nonce: bigint,\n gasLimit: bigint,\n params: EvmFeeParams,\n): EvmTxFields {\n const base = { chainId: ctx.config.chainId, nonce, gasLimit, ...call };\n return params.type === 'eip1559'\n ? {\n ...base,\n type: 'eip1559',\n maxFeePerGas: params.maxFeePerGas,\n maxPriorityFeePerGas: params.maxPriorityFeePerGas,\n }\n : { ...base, type: 'legacy', gasPrice: params.gasPrice };\n}\n\nfunction nonceOf(ordering: OrderingData | undefined): bigint {\n if (ordering?.kind !== 'nonce') {\n throw new StateError(\n 'INVALID_TRANSITION',\n 'an EVM transaction needs an allocated nonce',\n );\n }\n return ordering.nonce;\n}\n\n/**\n * Rebuilds an unsigned transaction's fields from its ordering, summary and fee: a stored\n * record holds plain data only, never an SDK object.\n */\nfunction unsignedFields(ctx: EvmContext, unsigned: UnsignedTx): EvmTxFields {\n const { ref } = parseAssetId(unsigned.summary.asset);\n const [output] = unsigned.summary.outputs;\n if (!output)\n throw new ValidationError('INVALID_INTENT', 'the unsigned transaction has no output');\n const transfer: Transfer = {\n to: output.to,\n amount: BigInt(output.amount),\n ...(ref === 'native' ? {} : { token: ref.contract }),\n };\n const { gasLimit, params } = feeOf(unsigned.fee.details);\n return fieldsOf(\n ctx,\n callOf(ctx.client, transfer),\n nonceOf(unsigned.ordering),\n gasLimit,\n params,\n );\n}\n\nfunction keyOf(keys: readonly WalletKey[]): WalletKey {\n const key = keys.find((k) => k.scheme === 'secp256k1-ecdsa');\n if (!key)\n throw new SigningError(\n 'SIGNER_UNAVAILABLE',\n 'no secp256k1 key for the sending wallet',\n );\n return key;\n}\n\nfunction unsignedTx(\n ctx: EvmContext,\n fields: EvmTxFields,\n fee: FeeEstimateDraft,\n key: WalletKey,\n summary: IntentSummary,\n): UnsignedTx {\n const { client } = ctx;\n return {\n payload: { encoding: 'hex', data: client.serializeUnsigned(fields) },\n signingRequests: [\n {\n id: 'r0',\n scheme: 'secp256k1-ecdsa',\n payload: fromHex(client.unsignedHash(fields)),\n payloadKind: 'digest',\n publicKey: key.publicKey,\n ...(key.keyRef ? { keyRef: key.keyRef } : {}),\n },\n ],\n ordering: { kind: 'nonce', nonce: fields.nonce },\n fee,\n summary,\n };\n}\n\nasync function priceFor(\n ctx: EvmContext,\n fee: FeeSpeed | FeeOverride,\n signal?: AbortSignal,\n): Promise<Price> {\n const { client, config } = ctx;\n if (typeof fee === 'object') {\n const { params, gasLimit } = parseFeeOverride(fee, config.feeModel);\n // An explicit fee above the ceiling is refused before any request.\n assertWithinCeiling(params, config.maxFeePerGas);\n return { speed: 'custom', params, ...(gasLimit !== undefined ? { gasLimit } : {}) };\n }\n // A node's suggestion is clamped to the ceiling, so no endpoint can raise it.\n if (config.feeModel === 'evm-legacy') {\n const gasPrice = await client.gasPrice(withSignal(READ, signal));\n return {\n speed: fee,\n params: capPrice(legacyPrice(gasPrice, fee), config.maxFeePerGas),\n };\n }\n const history = await client.feeHistory(\n FEE_HISTORY_BLOCKS,\n 'latest',\n FEE_PERCENTILES,\n withSignal(READ, signal),\n );\n const { params, baseFeePerGas } = feesFromHistory(\n history,\n fee,\n config.minPriorityFeePerGas,\n );\n return { speed: fee, params: capPrice(params, config.maxFeePerGas), baseFeePerGas };\n}\n\n/** OP Stack: the oracle's L1 data fee for these exact unsigned bytes. */\nasync function l1FeeFor(\n ctx: EvmContext,\n fields: EvmTxFields,\n signal?: AbortSignal,\n): Promise<bigint | undefined> {\n if (!ctx.config.l1DataFee) return undefined;\n const { client } = ctx;\n const data = client.abi.encodeGetL1Fee(client.serializeUnsigned(fields));\n const result = await client.call(\n { to: GAS_PRICE_ORACLE, data },\n 'latest',\n withSignal(READ, signal),\n );\n try {\n return client.abi.decodeUint256(result);\n } catch {\n throw new ProviderError('PROVIDER_UNAVAILABLE', 'the L1 fee oracle gave no fee');\n }\n}\n\nasync function draftFor(\n ctx: EvmContext,\n fields: EvmTxFields,\n price: Price,\n signal?: AbortSignal,\n): Promise<FeeEstimateDraft> {\n const l1Fee = await l1FeeFor(ctx, fields, signal);\n return feeDraft(price.speed, fields.gasLimit, price.params, {\n ...(price.baseFeePerGas !== undefined ? { baseFeePerGas: price.baseFeePerGas } : {}),\n ...(l1Fee !== undefined ? { l1Fee } : {}),\n });\n}\n\n/** geth's estimate reached its gas cap: the call fails at any gas limit. */\nconst GAS_ALLOWANCE = /^gas required exceeds allowance/i;\n\n/**\n * The node's gas estimate; a failing call or a shortfall becomes a clear pre-signing failure.\n * A revert, a VM execution failure or an exhausted gas allowance is the call's own\n * failure, tested first so that a token's revert text naming \"insufficient funds\" still gets\n * the balance check. Any other error is the provider's and is rethrown unchanged.\n */\nasync function estimateGas(\n ctx: EvmContext,\n from: string,\n transfer: Transfer,\n signal?: AbortSignal,\n): Promise<bigint> {\n try {\n return await ctx.client.estimateGas(\n { from, ...callOf(ctx.client, transfer) },\n withSignal(READ, signal),\n );\n } catch (error) {\n const definitive = isCryptoAioError(error, 'RPC_ERROR') && !error.ambiguous;\n const message = definitive ? String(error.details?.rpcMessage ?? error.message) : '';\n const fails =\n isRevert(error) || isExecutionFailure(error) || GAS_ALLOWANCE.test(message);\n if (!fails) {\n if (/insufficient funds/i.test(message)) {\n throw new ChainError(\n 'INSUFFICIENT_FUNDS',\n 'insufficient funds for this transfer',\n );\n }\n throw error;\n }\n if (transfer.token !== undefined) {\n const available = await erc20Balance(\n ctx.client,\n transfer.token,\n from,\n withSignal(READ, signal),\n );\n if (available < transfer.amount) {\n throw new ChainError(\n 'INSUFFICIENT_FUNDS',\n 'insufficient token balance for this transfer',\n {\n details: {\n required: transfer.amount.toString(),\n available: available.toString(),\n },\n },\n );\n }\n }\n throw new ValidationError('INVALID_INTENT', 'the transfer would fail');\n }\n}\n\nexport function createEvmBuilder(ctx: EvmContext): TxBuilder {\n const { client } = ctx;\n return {\n async estimateFee(intent, build: BuildContext) {\n const transfer = transferOf(intent);\n const price = await priceFor(ctx, intent.fee, build.signal);\n const gasLimit =\n price.gasLimit ??\n gasLimitFrom(await estimateGas(ctx, intent.from, transfer, build.signal));\n const nonce = build.ordering?.kind === 'nonce' ? build.ordering.nonce : 0n;\n const fields = fieldsOf(\n ctx,\n callOf(client, transfer),\n nonce,\n gasLimit,\n price.params,\n );\n return draftFor(ctx, fields, price, build.signal);\n },\n\n async checkFunds(intent, fee, build) {\n const transfer = transferOf(intent);\n if (transfer.token !== undefined) {\n const available = await erc20Balance(\n client,\n transfer.token,\n intent.from,\n withSignal(READ, build.signal),\n );\n if (available < transfer.amount) {\n return {\n ok: false,\n asset: { standard: 'erc20', contract: transfer.token },\n required: transfer.amount,\n available,\n };\n }\n }\n const cost = fee.charges.reduce(\n (sum, c) => (c.asset === 'native' ? sum + c.amount : sum),\n 0n,\n );\n const required = cost + (transfer.token === undefined ? transfer.amount : 0n);\n const available = await client.getBalance(\n intent.from,\n 'latest',\n withSignal(READ, build.signal),\n );\n return available >= required\n ? { ok: true }\n : { ok: false, asset: 'native', required, available };\n },\n\n async build(intent, fee, build) {\n const transfer = transferOf(intent);\n const { gasLimit, params } = feeOf(fee.details);\n const model = params.type === 'eip1559' ? 'evm-1559' : 'evm-legacy';\n if (model !== ctx.config.feeModel) {\n throw new ValidationError(\n 'INVALID_INTENT',\n `this network takes ${ctx.config.feeModel} fees`,\n );\n }\n // The ceiling is checked again, whatever produced the fee object.\n assertWithinCeiling(params, ctx.config.maxFeePerGas);\n const fields = fieldsOf(\n ctx,\n callOf(client, transfer),\n nonceOf(build.ordering),\n gasLimit,\n params,\n );\n return unsignedTx(ctx, fields, fee, keyOf(build.keys), {\n asset: assetId(ctx.chain.id, ctx.network.id, intent.asset),\n outputs: [{ to: transfer.to, amount: transfer.amount.toString() }],\n });\n },\n\n async assemble(unsigned, signatures) {\n const request = unsigned.signingRequests[0];\n const signature = signatures.find((s) => s.requestId === request?.id);\n if (\n !request ||\n !signature ||\n signature.bytes.length !== 64 ||\n (signature.recovery !== 0 && signature.recovery !== 1)\n ) {\n throw new SigningError('SIGNING_FAILED', 'missing signature for request r0');\n }\n const mismatch = () =>\n new SigningError(\n 'SIGNING_FAILED',\n 'the unsigned payload or its digest does not match its fee and summary',\n );\n let fields: EvmTxFields;\n try {\n fields = unsignedFields(ctx, unsigned);\n } catch {\n throw mismatch();\n }\n // The signature must be over these fields' digest, or it signs other bytes.\n if (\n client.serializeUnsigned(fields) !== unsigned.payload.data ||\n !equalBytes(request.payload, fromHex(client.unsignedHash(fields)))\n ) {\n throw mismatch();\n }\n const { raw, hash } = client.serializeSigned(fields, {\n r: toHex(signature.bytes.slice(0, 32), true),\n s: toHex(signature.bytes.slice(32), true),\n yParity: signature.recovery,\n });\n return {\n raw: { encoding: 'hex', data: raw },\n ref: { id: hash, idKind: 'tx-hash', canonical: true },\n };\n },\n };\n}\n\nexport function createEvmBroadcaster(client: EvmClient, chainId: bigint): Broadcaster {\n return {\n async broadcast(signed, options = {}): Promise<BroadcastResult> {\n try {\n await client.sendRawTransaction(signed.raw.data, {\n purpose: 'broadcast',\n retry: 'ambiguous-on-failure',\n ...(options.fanout !== undefined ? { fanout: options.fanout } : {}),\n ...(options.signal ? { signal: options.signal } : {}),\n });\n return { kind: 'accepted' };\n } catch (error) {\n // An ambiguous error may hide a delivered transaction; it is never classified.\n // A rejection stands only when its reason holds for the bytes we sent.\n if (isCryptoAioError(error, 'RPC_ERROR') && !error.ambiguous) {\n return classifyOwnBroadcast(\n String(error.details?.rpcMessage ?? error.message),\n signed.raw.data,\n chainId,\n );\n }\n throw error;\n }\n },\n };\n}\n\n/** Same-nonce replace and cancel under the network's bump; absent without a mempool. */\nexport function createEvmReplacement(ctx: EvmContext): ReplacementPolicy | undefined {\n const { config } = ctx;\n const bump = config.minBumpPercent;\n if (bump === undefined) return undefined;\n const prices =\n config.feeModel === 'evm-legacy' ? 'the gas price' : 'the fee cap and the tip';\n const tooLow = (what: string) =>\n new ChainError('FEE_TOO_LOW', `${what} must raise ${prices} by at least ${bump}%`);\n const keyFrom = (previous: UnsignedTx): WalletKey => {\n const request = previous.signingRequests[0];\n if (!request)\n throw new SigningError('SIGNER_UNAVAILABLE', 'the previous attempt has no key');\n return {\n scheme: request.scheme,\n publicKey: request.publicKey,\n ...(request.keyRef ? { keyRef: request.keyRef } : {}),\n };\n };\n return {\n replace: config.capabilities.has('replace-fee'),\n cancel: config.capabilities.has('cancel'),\n\n async buildReplacement(previous, fee, build) {\n const before = feeOf(previous.fee.details);\n const price = await priceFor(ctx, fee, build.signal);\n if (!meetsBump(before.params, price.params, bump)) throw tooLow('a replacement');\n const old = unsignedFields(ctx, previous);\n const fields = fieldsOf(\n ctx,\n { to: old.to, value: old.value, data: old.data },\n old.nonce,\n price.gasLimit ?? before.gasLimit,\n price.params,\n );\n return unsignedTx(\n ctx,\n fields,\n await draftFor(ctx, fields, price, build.signal),\n keyFrom(previous),\n previous.summary,\n );\n },\n\n async buildCancel(previous, build, fee) {\n const before = feeOf(previous.fee.details);\n const price: Price =\n fee === undefined\n ? { speed: 'custom', params: minimumBump(before.params, bump) }\n : await priceFor(ctx, fee, build.signal);\n if (!meetsBump(before.params, price.params, bump)) throw tooLow('a cancel');\n // A cancel whose least bump would pay above the ceiling is refused.\n assertWithinCeiling(price.params, config.maxFeePerGas);\n const nonce = nonceOf(previous.ordering);\n const fields = fieldsOf(\n ctx,\n { to: build.from, value: 0n, data: '0x' },\n nonce,\n price.gasLimit ?? TRANSFER_GAS,\n price.params,\n );\n return unsignedTx(\n ctx,\n fields,\n await draftFor(ctx, fields, price, build.signal),\n keyFrom(previous),\n {\n asset: assetId(ctx.chain.id, ctx.network.id, 'native'),\n outputs: [{ to: build.from, amount: '0' }],\n },\n );\n },\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"builder.js","sourceRoot":"","sources":["../../../src/adapters/evm/builder.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Fees, funds, building, assembling, broadcasting, and same-nonce replace and cancel.\n * One output per transfer, native or ERC-20 `transfer`.\n */\nimport type {\n BroadcastResult,\n Broadcaster,\n BuildContext,\n ReplacementPolicy,\n TxBuilder,\n WalletKey,\n} from '../../core/driver/types';\nimport {\n ChainError,\n ProviderError,\n SigningError,\n StateError,\n UnsupportedCapabilityError,\n ValidationError,\n isCryptoAioError,\n} from '../../core/errors/error';\nimport { assetId, parseAssetId } from '../../core/model/asset';\nimport type { FeeEstimateDraft, FeeOverride, FeeSpeed } from '../../core/model/fee';\nimport type { DriverIntent, IntentSummary } from '../../core/model/intent';\nimport type { OrderingData } from '../../core/model/ordering';\nimport type { UnsignedTx } from '../../core/model/transaction';\nimport { equalBytes, fromHex, toHex } from '../../core/util/bytes';\nimport { classifyOwnBroadcast } from './errors';\nimport {\n FEE_HISTORY_BLOCKS,\n FEE_PERCENTILES,\n TRANSFER_GAS,\n assertWithinCeiling,\n assertWithinGasLimit,\n capPrice,\n comparePrices,\n feeDraft,\n feeOf,\n feesFromHistory,\n gasLimitFrom,\n legacyPrice,\n meetsBump,\n minimumBump,\n parseFeeOverride,\n type EvmFeeParams,\n} from './fees';\nimport { GAS_PRICE_ORACLE } from './network';\nimport {\n READ,\n callIfPresent,\n erc20Balance,\n erc20Deprecated,\n isExecutionFailure,\n isRevert,\n withSignal,\n type EvmContext,\n} from './reader';\nimport type { EvmClient, EvmTxFields } from './types';\n\n/** One transfer: `token` is the ERC-20 contract, absent for the native asset. */\ninterface Transfer {\n readonly to: string;\n readonly amount: bigint;\n readonly token?: string;\n}\n\ninterface Price {\n readonly speed: FeeSpeed | 'custom';\n readonly params: EvmFeeParams;\n readonly baseFeePerGas?: bigint;\n readonly gasLimit?: bigint;\n}\n\nfunction transferOf(intent: DriverIntent): Transfer {\n if (intent.memo !== undefined) {\n throw new UnsupportedCapabilityError(\n 'UNSUPPORTED_CAPABILITY',\n 'EVM transfers carry no memo',\n );\n }\n const [output] = intent.outputs;\n if (!output || intent.outputs.length !== 1) {\n throw new ValidationError('INVALID_INTENT', 'an EVM transfer has exactly one output');\n }\n if (intent.asset === 'native') return { to: output.to, amount: output.amount };\n if (intent.asset.standard !== 'erc20') {\n throw new ValidationError('ASSET_RESOLUTION', `EVM tokens use the 'erc20' standard`);\n }\n return { to: output.to, amount: output.amount, token: intent.asset.contract };\n}\n\n/** The call a transfer makes: a value transfer, or `transfer(to, amount)` on the token. */\nfunction callOf(\n client: EvmClient,\n transfer: Transfer,\n): { to: string; value: bigint; data: string } {\n return transfer.token === undefined\n ? { to: transfer.to, value: transfer.amount, data: '0x' }\n : {\n to: transfer.token,\n value: 0n,\n data: client.abi.encodeTransfer(transfer.to, transfer.amount),\n };\n}\n\nfunction fieldsOf(\n ctx: EvmContext,\n call: { to: string; value: bigint; data: string },\n nonce: bigint,\n gasLimit: bigint,\n params: EvmFeeParams,\n): EvmTxFields {\n const base = { chainId: ctx.config.chainId, nonce, gasLimit, ...call };\n return params.type === 'eip1559'\n ? {\n ...base,\n type: 'eip1559',\n maxFeePerGas: params.maxFeePerGas,\n maxPriorityFeePerGas: params.maxPriorityFeePerGas,\n }\n : { ...base, type: 'legacy', gasPrice: params.gasPrice };\n}\n\nfunction nonceOf(ordering: OrderingData | undefined): bigint {\n if (ordering?.kind !== 'nonce') {\n throw new StateError(\n 'INVALID_TRANSITION',\n 'an EVM transaction needs an allocated nonce',\n );\n }\n return ordering.nonce;\n}\n\n/**\n * Rebuilds an unsigned transaction's fields from its ordering, summary and fee: a stored\n * record holds plain data only, never an SDK object.\n */\nfunction unsignedFields(ctx: EvmContext, unsigned: UnsignedTx): EvmTxFields {\n const { ref } = parseAssetId(unsigned.summary.asset);\n const [output] = unsigned.summary.outputs;\n if (!output)\n throw new ValidationError('INVALID_INTENT', 'the unsigned transaction has no output');\n const transfer: Transfer = {\n to: output.to,\n amount: BigInt(output.amount),\n ...(ref === 'native' ? {} : { token: ref.contract }),\n };\n const { gasLimit, params } = feeOf(unsigned.fee.details);\n return fieldsOf(\n ctx,\n callOf(ctx.client, transfer),\n nonceOf(unsigned.ordering),\n gasLimit,\n params,\n );\n}\n\nfunction keyOf(keys: readonly WalletKey[]): WalletKey {\n const key = keys.find((k) => k.scheme === 'secp256k1-ecdsa');\n if (!key)\n throw new SigningError(\n 'SIGNER_UNAVAILABLE',\n 'no secp256k1 key for the sending wallet',\n );\n return key;\n}\n\nfunction unsignedTx(\n ctx: EvmContext,\n fields: EvmTxFields,\n fee: FeeEstimateDraft,\n key: WalletKey,\n summary: IntentSummary,\n): UnsignedTx {\n const { client } = ctx;\n return {\n payload: { encoding: 'hex', data: client.serializeUnsigned(fields) },\n signingRequests: [\n {\n id: 'r0',\n scheme: 'secp256k1-ecdsa',\n payload: fromHex(client.unsignedHash(fields)),\n payloadKind: 'digest',\n publicKey: key.publicKey,\n ...(key.keyRef ? { keyRef: key.keyRef } : {}),\n },\n ],\n ordering: { kind: 'nonce', nonce: fields.nonce },\n fee,\n summary,\n };\n}\n\nasync function priceFor(\n ctx: EvmContext,\n fee: FeeSpeed | FeeOverride,\n signal?: AbortSignal,\n): Promise<Price> {\n const { client, config } = ctx;\n if (typeof fee === 'object') {\n const { params, gasLimit } = parseFeeOverride(fee, config.feeModel);\n // An explicit fee above either bound is refused before any request.\n assertWithinCeiling(params, config.maxFeePerGas);\n if (gasLimit !== undefined) assertWithinGasLimit(gasLimit, config.maxGasLimit);\n return { speed: 'custom', params, ...(gasLimit !== undefined ? { gasLimit } : {}) };\n }\n // A node's suggestion is clamped to the ceiling, so no endpoint can raise it.\n if (config.feeModel === 'evm-legacy') {\n const gasPrice = await client.gasPrice(withSignal(READ, signal));\n return {\n speed: fee,\n params: capPrice(legacyPrice(gasPrice, fee), config.maxFeePerGas),\n };\n }\n const history = await client.feeHistory(\n FEE_HISTORY_BLOCKS,\n 'latest',\n FEE_PERCENTILES,\n withSignal(READ, signal),\n );\n const { params, baseFeePerGas } = feesFromHistory(\n history,\n fee,\n config.minPriorityFeePerGas,\n );\n return { speed: fee, params: capPrice(params, config.maxFeePerGas), baseFeePerGas };\n}\n\n/** OP Stack: the oracle's L1 data fee for these exact unsigned bytes. */\nasync function l1FeeFor(\n ctx: EvmContext,\n fields: EvmTxFields,\n signal?: AbortSignal,\n): Promise<bigint | undefined> {\n if (!ctx.config.l1DataFee) return undefined;\n const { client } = ctx;\n const data = client.abi.encodeGetL1Fee(client.serializeUnsigned(fields));\n const result = await client.call(\n { to: GAS_PRICE_ORACLE, data },\n 'latest',\n withSignal(READ, signal),\n );\n try {\n return client.abi.decodeUint256(result);\n } catch {\n throw new ProviderError('PROVIDER_UNAVAILABLE', 'the L1 fee oracle gave no fee');\n }\n}\n\n/**\n * OP Stack since Isthmus: the oracle's operator fee (`getOperatorFee`) for the whole gas\n * limit. The fee grows with the gas used, so the limit gives an upper bound at the chain's\n * current operator settings, as the `network` charge does at the fee cap; the predeploy\n * applies the formula of the chain's fork (Isthmus or Jovian). `undefined` where nothing\n * is charged: a zero fee, or a predeploy that has no such method yet (a revert, or `0x`).\n * A node error is retryable (`callIfPresent`), and a malformed answer is a retryable\n * `PROVIDER_UNAVAILABLE`, never no fee.\n */\nasync function operatorFeeFor(\n ctx: EvmContext,\n gasLimit: bigint,\n signal?: AbortSignal,\n): Promise<bigint | undefined> {\n if (!ctx.config.l1DataFee) return undefined;\n const { client } = ctx;\n const result = await callIfPresent(\n client,\n { to: GAS_PRICE_ORACLE, data: client.abi.encodeGetOperatorFee(gasLimit) },\n withSignal(READ, signal),\n );\n if (result === null || result === '0x') return undefined;\n let fee: bigint;\n try {\n fee = client.abi.decodeUint256(result);\n } catch {\n throw new ProviderError(\n 'PROVIDER_UNAVAILABLE',\n 'the operator fee oracle gave no fee',\n );\n }\n return fee === 0n ? undefined : fee;\n}\n\n/** The fee draft for `fields`, with the OP Stack charges read side by side. */\nasync function draftFor(\n ctx: EvmContext,\n fields: EvmTxFields,\n price: Price,\n signal?: AbortSignal,\n): Promise<FeeEstimateDraft> {\n const [l1Fee, operatorFee] = await Promise.all([\n l1FeeFor(ctx, fields, signal),\n operatorFeeFor(ctx, fields.gasLimit, signal),\n ]);\n return feeDraft(price.speed, fields.gasLimit, price.params, {\n ...(price.baseFeePerGas !== undefined ? { baseFeePerGas: price.baseFeePerGas } : {}),\n ...(l1Fee !== undefined ? { l1Fee } : {}),\n ...(operatorFee !== undefined ? { operatorFee } : {}),\n });\n}\n\n/**\n * Refuses a transfer of a token whose contract says it is deprecated. Tether's\n * `TetherToken` (USDT on Ethereum) forwards a deprecated contract's `transfer` to its\n * upgraded contract, which moves the value and emits the `Transfer` event, so the transfer\n * estimates and executes, and the verdict, which reads the old contract's event, finds no\n * evidence of it. Read once per estimate, before `eth_estimateGas` (which such a transfer\n * passes); the core estimates before every build. One endpoint's answer, as for the\n * builder's other token reads, not the proof quorum's: a `true` can only refuse before\n * signing, the safe direction (as one endpoint's revert in `eth_estimateGas` already\n * does), and a wrong `false` leaves the transfer where it was without the guard.\n */\nasync function refuseDeprecated(\n ctx: EvmContext,\n token: string,\n signal?: AbortSignal,\n): Promise<void> {\n if (await erc20Deprecated(ctx.client, token, withSignal(READ, signal))) {\n throw new ValidationError(\n 'ASSET_RESOLUTION',\n 'the token contract is deprecated in favour of an upgraded contract; the asset must be re-registered at the upgraded contract',\n );\n }\n}\n\n/** geth's estimate reached its gas cap: the call fails at any gas limit. */\nconst GAS_ALLOWANCE = /^gas required exceeds allowance/i;\n\n/**\n * The node's gas estimate; a failing call or a shortfall becomes a clear pre-signing failure.\n * A revert, a VM execution failure or an exhausted gas allowance is the call's own\n * failure, tested first so that a token's revert text naming \"insufficient funds\" still gets\n * the balance check. Any other error is the provider's and is rethrown unchanged.\n */\nasync function estimateGas(\n ctx: EvmContext,\n from: string,\n transfer: Transfer,\n signal?: AbortSignal,\n): Promise<bigint> {\n try {\n return await ctx.client.estimateGas(\n { from, ...callOf(ctx.client, transfer) },\n withSignal(READ, signal),\n );\n } catch (error) {\n const definitive = isCryptoAioError(error, 'RPC_ERROR') && !error.ambiguous;\n const message = definitive ? String(error.details?.rpcMessage ?? error.message) : '';\n const fails =\n isRevert(error) || isExecutionFailure(error) || GAS_ALLOWANCE.test(message);\n if (!fails) {\n if (/insufficient funds/i.test(message)) {\n throw new ChainError(\n 'INSUFFICIENT_FUNDS',\n 'insufficient funds for this transfer',\n );\n }\n throw error;\n }\n if (transfer.token !== undefined) {\n const available = await erc20Balance(\n ctx.client,\n transfer.token,\n from,\n withSignal(READ, signal),\n );\n if (available < transfer.amount) {\n throw new ChainError(\n 'INSUFFICIENT_FUNDS',\n 'insufficient token balance for this transfer',\n {\n details: {\n required: transfer.amount.toString(),\n available: available.toString(),\n },\n },\n );\n }\n }\n throw new ValidationError('INVALID_INTENT', 'the transfer would fail');\n }\n}\n\nexport function createEvmBuilder(ctx: EvmContext): TxBuilder {\n const { client } = ctx;\n return {\n async estimateFee(intent, build: BuildContext) {\n const transfer = transferOf(intent);\n const price = await priceFor(ctx, intent.fee, build.signal);\n if (transfer.token !== undefined) {\n await refuseDeprecated(ctx, transfer.token, build.signal);\n }\n const gasLimit =\n price.gasLimit ??\n gasLimitFrom(await estimateGas(ctx, intent.from, transfer, build.signal));\n // The estimate with its headroom is what would be signed, so that is what is bounded.\n assertWithinGasLimit(gasLimit, ctx.config.maxGasLimit);\n const nonce = build.ordering?.kind === 'nonce' ? build.ordering.nonce : 0n;\n const fields = fieldsOf(\n ctx,\n callOf(client, transfer),\n nonce,\n gasLimit,\n price.params,\n );\n return draftFor(ctx, fields, price, build.signal);\n },\n\n async checkFunds(intent, fee, build) {\n const transfer = transferOf(intent);\n if (transfer.token !== undefined) {\n const available = await erc20Balance(\n client,\n transfer.token,\n intent.from,\n withSignal(READ, build.signal),\n );\n if (available < transfer.amount) {\n return {\n ok: false,\n asset: { standard: 'erc20', contract: transfer.token },\n required: transfer.amount,\n available,\n };\n }\n }\n const cost = fee.charges.reduce(\n (sum, c) => (c.asset === 'native' ? sum + c.amount : sum),\n 0n,\n );\n const required = cost + (transfer.token === undefined ? transfer.amount : 0n);\n const available = await client.getBalance(\n intent.from,\n 'latest',\n withSignal(READ, build.signal),\n );\n return available >= required\n ? { ok: true }\n : { ok: false, asset: 'native', required, available };\n },\n\n async build(intent, fee, build) {\n const transfer = transferOf(intent);\n const { gasLimit, params } = feeOf(fee.details);\n const model = params.type === 'eip1559' ? 'evm-1559' : 'evm-legacy';\n if (model !== ctx.config.feeModel) {\n throw new ValidationError(\n 'INVALID_INTENT',\n `this network takes ${ctx.config.feeModel} fees`,\n );\n }\n // The bounds are checked again, whatever produced the fee object.\n assertWithinCeiling(params, ctx.config.maxFeePerGas);\n assertWithinGasLimit(gasLimit, ctx.config.maxGasLimit);\n const fields = fieldsOf(\n ctx,\n callOf(client, transfer),\n nonceOf(build.ordering),\n gasLimit,\n params,\n );\n return unsignedTx(ctx, fields, fee, keyOf(build.keys), {\n asset: assetId(ctx.chain.id, ctx.network.id, intent.asset),\n outputs: [{ to: transfer.to, amount: transfer.amount.toString() }],\n });\n },\n\n async assemble(unsigned, signatures) {\n const request = unsigned.signingRequests[0];\n const signature = signatures.find((s) => s.requestId === request?.id);\n if (\n !request ||\n !signature ||\n signature.bytes.length !== 64 ||\n (signature.recovery !== 0 && signature.recovery !== 1)\n ) {\n throw new SigningError('SIGNING_FAILED', 'missing signature for request r0');\n }\n const mismatch = () =>\n new SigningError(\n 'SIGNING_FAILED',\n 'the unsigned payload or its digest does not match its fee and summary',\n );\n let fields: EvmTxFields;\n try {\n fields = unsignedFields(ctx, unsigned);\n } catch {\n throw mismatch();\n }\n // The signature must be over these fields' digest, or it signs other bytes.\n if (\n client.serializeUnsigned(fields) !== unsigned.payload.data ||\n !equalBytes(request.payload, fromHex(client.unsignedHash(fields)))\n ) {\n throw mismatch();\n }\n const { raw, hash } = client.serializeSigned(fields, {\n r: toHex(signature.bytes.slice(0, 32), true),\n s: toHex(signature.bytes.slice(32), true),\n yParity: signature.recovery,\n });\n return {\n raw: { encoding: 'hex', data: raw },\n ref: { id: hash, idKind: 'tx-hash', canonical: true },\n };\n },\n };\n}\n\nexport function createEvmBroadcaster(client: EvmClient, chainId: bigint): Broadcaster {\n return {\n async broadcast(signed, options = {}): Promise<BroadcastResult> {\n try {\n await client.sendRawTransaction(signed.raw.data, {\n purpose: 'broadcast',\n retry: 'ambiguous-on-failure',\n ...(options.fanout !== undefined ? { fanout: options.fanout } : {}),\n ...(options.signal ? { signal: options.signal } : {}),\n });\n return { kind: 'accepted' };\n } catch (error) {\n // An ambiguous error may hide a delivered transaction; it is never classified.\n // A rejection stands only when its reason holds for the bytes we sent.\n if (isCryptoAioError(error, 'RPC_ERROR') && !error.ambiguous) {\n return classifyOwnBroadcast(\n String(error.details?.rpcMessage ?? error.message),\n signed.raw.data,\n chainId,\n );\n }\n throw error;\n }\n },\n };\n}\n\n/** Same-nonce replace and cancel under the network's bump; absent without a mempool. */\nexport function createEvmReplacement(ctx: EvmContext): ReplacementPolicy | undefined {\n const { config } = ctx;\n const bump = config.minBumpPercent;\n if (bump === undefined) return undefined;\n const prices =\n config.feeModel === 'evm-legacy' ? 'the gas price' : 'the fee cap and the tip';\n const tooLow = (what: string) =>\n new ChainError('FEE_TOO_LOW', `${what} must raise ${prices} by at least ${bump}%`);\n const keyFrom = (previous: UnsignedTx): WalletKey => {\n const request = previous.signingRequests[0];\n if (!request)\n throw new SigningError('SIGNER_UNAVAILABLE', 'the previous attempt has no key');\n return {\n scheme: request.scheme,\n publicKey: request.publicKey,\n ...(request.keyRef ? { keyRef: request.keyRef } : {}),\n };\n };\n return {\n replace: config.capabilities.has('replace-fee'),\n cancel: config.capabilities.has('cancel'),\n\n comparePrice: (a, b) =>\n comparePrices(feeOf(a.fee.details).params, feeOf(b.fee.details).params),\n\n async buildReplacement(previous, fee, build) {\n const before = feeOf(previous.fee.details);\n const price = await priceFor(ctx, fee, build.signal);\n if (!meetsBump(before.params, price.params, bump)) throw tooLow('a replacement');\n const old = unsignedFields(ctx, previous);\n // The original's gas limit too: no replacement signs one above the bound.\n const gasLimit = price.gasLimit ?? before.gasLimit;\n assertWithinGasLimit(gasLimit, config.maxGasLimit);\n const fields = fieldsOf(\n ctx,\n { to: old.to, value: old.value, data: old.data },\n old.nonce,\n gasLimit,\n price.params,\n );\n return unsignedTx(\n ctx,\n fields,\n await draftFor(ctx, fields, price, build.signal),\n keyFrom(previous),\n previous.summary,\n );\n },\n\n async buildCancel(previous, build, fee) {\n const before = feeOf(previous.fee.details);\n const price: Price =\n fee === undefined\n ? { speed: 'custom', params: minimumBump(before.params, bump) }\n : await priceFor(ctx, fee, build.signal);\n if (!meetsBump(before.params, price.params, bump)) throw tooLow('a cancel');\n // A cancel whose least bump would pay above the ceiling is refused.\n assertWithinCeiling(price.params, config.maxFeePerGas);\n const nonce = nonceOf(previous.ordering);\n // A self-transfer needs 21,000 gas, which every bound allows; an explicit fee's\n // `gasLimit` was bounded when it was parsed.\n const fields = fieldsOf(\n ctx,\n { to: build.from, value: 0n, data: '0x' },\n nonce,\n price.gasLimit ?? TRANSFER_GAS,\n price.params,\n );\n return unsignedTx(\n ctx,\n fields,\n await draftFor(ctx, fields, price, build.signal),\n keyFrom(previous),\n {\n asset: assetId(ctx.chain.id, ctx.network.id, 'native'),\n outputs: [{ to: build.from, amount: '0' }],\n },\n );\n },\n };\n}\n"]}
|
|
@@ -78,7 +78,12 @@ function evmObservation(abi, tx, receipt) {
|
|
|
78
78
|
if (!receipt || receipt.status === 0 || tokenTransferLanded(abi, tx, receipt)) {
|
|
79
79
|
return observation;
|
|
80
80
|
}
|
|
81
|
-
return {
|
|
81
|
+
return {
|
|
82
|
+
...observation,
|
|
83
|
+
success: false,
|
|
84
|
+
reason: 'token transfer failed',
|
|
85
|
+
failure: 'unevidenced',
|
|
86
|
+
};
|
|
82
87
|
}
|
|
83
88
|
/** bor's fee log or native transfer log, from the MRC20 predeploy. */
|
|
84
89
|
const isPolygonSystemLog = (log) => log.address.toLowerCase() === network_1.POLYGON_FEE_LOG.address &&
|