crypto-aio 0.0.2 → 0.1.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 +17 -0
- package/README.md +144 -14
- package/dist/adapters/avalanche/address.d.ts +15 -0
- package/dist/adapters/avalanche/address.js +74 -0
- package/dist/adapters/avalanche/address.js.map +1 -0
- package/dist/adapters/avalanche/api.d.ts +100 -0
- package/dist/adapters/avalanche/api.js +381 -0
- package/dist/adapters/avalanche/api.js.map +1 -0
- package/dist/adapters/avalanche/builder.d.ts +13 -0
- package/dist/adapters/avalanche/builder.js +336 -0
- package/dist/adapters/avalanche/builder.js.map +1 -0
- package/dist/adapters/avalanche/cb58.d.ts +7 -0
- package/dist/adapters/avalanche/cb58.js +49 -0
- package/dist/adapters/avalanche/cb58.js.map +1 -0
- package/dist/adapters/avalanche/chains.d.ts +21 -0
- package/dist/adapters/avalanche/chains.js +79 -0
- package/dist/adapters/avalanche/chains.js.map +1 -0
- package/dist/adapters/avalanche/codec.d.ts +94 -0
- package/dist/adapters/avalanche/codec.js +371 -0
- package/dist/adapters/avalanche/codec.js.map +1 -0
- package/dist/adapters/avalanche/context.d.ts +59 -0
- package/dist/adapters/avalanche/context.js +114 -0
- package/dist/adapters/avalanche/context.js.map +1 -0
- package/dist/adapters/avalanche/decode.d.ts +16 -0
- package/dist/adapters/avalanche/decode.js +101 -0
- package/dist/adapters/avalanche/decode.js.map +1 -0
- package/dist/adapters/avalanche/driver.d.ts +22 -0
- package/dist/adapters/avalanche/driver.js +81 -0
- package/dist/adapters/avalanche/driver.js.map +1 -0
- package/dist/adapters/avalanche/errors.d.ts +18 -0
- package/dist/adapters/avalanche/errors.js +61 -0
- package/dist/adapters/avalanche/errors.js.map +1 -0
- package/dist/adapters/avalanche/fees.d.ts +23 -0
- package/dist/adapters/avalanche/fees.js +105 -0
- package/dist/adapters/avalanche/fees.js.map +1 -0
- package/dist/adapters/avalanche/index.d.ts +19 -0
- package/dist/adapters/avalanche/index.js +8 -0
- package/dist/adapters/avalanche/index.js.map +1 -0
- package/dist/adapters/avalanche/network.d.ts +37 -0
- package/dist/adapters/avalanche/network.js +135 -0
- package/dist/adapters/avalanche/network.js.map +1 -0
- package/dist/adapters/avalanche/plugin.d.ts +21 -0
- package/dist/adapters/avalanche/plugin.js +46 -0
- package/dist/adapters/avalanche/plugin.js.map +1 -0
- package/dist/adapters/avalanche/presets.d.ts +6 -0
- package/dist/adapters/avalanche/presets.js +86 -0
- package/dist/adapters/avalanche/presets.js.map +1 -0
- package/dist/adapters/avalanche/proofs.d.ts +41 -0
- package/dist/adapters/avalanche/proofs.js +270 -0
- package/dist/adapters/avalanche/proofs.js.map +1 -0
- package/dist/adapters/avalanche/reader.d.ts +40 -0
- package/dist/adapters/avalanche/reader.js +231 -0
- package/dist/adapters/avalanche/reader.js.map +1 -0
- package/dist/adapters/avalanche/sdk.d.ts +182 -0
- package/dist/adapters/avalanche/sdk.js +21 -0
- package/dist/adapters/avalanche/sdk.js.map +1 -0
- package/dist/adapters/avalanche/types.d.ts +86 -0
- package/dist/{type/common.js → adapters/avalanche/types.js} +1 -1
- package/dist/adapters/avalanche/types.js.map +1 -0
- package/dist/adapters/evm/builder.d.ts +11 -0
- package/dist/adapters/evm/builder.js +326 -0
- package/dist/adapters/evm/builder.js.map +1 -0
- package/dist/adapters/evm/chains.d.ts +6 -0
- package/dist/adapters/evm/chains.js +203 -0
- package/dist/adapters/evm/chains.js.map +1 -0
- package/dist/adapters/evm/client.d.ts +84 -0
- package/dist/adapters/evm/client.js +335 -0
- package/dist/adapters/evm/client.js.map +1 -0
- package/dist/adapters/evm/decode.d.ts +35 -0
- package/dist/adapters/evm/decode.js +170 -0
- package/dist/adapters/evm/decode.js.map +1 -0
- package/dist/adapters/evm/driver.d.ts +8 -0
- package/dist/adapters/evm/driver.js +61 -0
- package/dist/adapters/evm/driver.js.map +1 -0
- package/dist/adapters/evm/errors.d.ts +20 -0
- package/dist/adapters/evm/errors.js +110 -0
- package/dist/adapters/evm/errors.js.map +1 -0
- package/dist/adapters/evm/ethers-client.d.ts +43 -0
- package/dist/adapters/evm/ethers-client.js +135 -0
- package/dist/adapters/evm/ethers-client.js.map +1 -0
- package/dist/adapters/evm/fees.d.ts +79 -0
- package/dist/adapters/evm/fees.js +234 -0
- package/dist/adapters/evm/fees.js.map +1 -0
- package/dist/adapters/evm/index.d.ts +20 -0
- package/dist/adapters/evm/index.js +11 -0
- package/dist/adapters/evm/index.js.map +1 -0
- package/dist/adapters/evm/network.d.ts +60 -0
- package/dist/adapters/evm/network.js +131 -0
- package/dist/adapters/evm/network.js.map +1 -0
- package/dist/adapters/evm/plugin.d.ts +36 -0
- package/dist/adapters/evm/plugin.js +102 -0
- package/dist/adapters/evm/plugin.js.map +1 -0
- package/dist/adapters/evm/presets.d.ts +2 -0
- package/dist/adapters/evm/presets.js +105 -0
- package/dist/adapters/evm/presets.js.map +1 -0
- package/dist/adapters/evm/proofs.d.ts +19 -0
- package/dist/adapters/evm/proofs.js +358 -0
- package/dist/adapters/evm/proofs.js.map +1 -0
- package/dist/adapters/evm/rawtx.d.ts +25 -0
- package/dist/adapters/evm/rawtx.js +176 -0
- package/dist/adapters/evm/rawtx.js.map +1 -0
- package/dist/adapters/evm/reader.d.ts +65 -0
- package/dist/adapters/evm/reader.js +292 -0
- package/dist/adapters/evm/reader.js.map +1 -0
- package/dist/adapters/evm/rpc.d.ts +39 -0
- package/dist/adapters/evm/rpc.js +152 -0
- package/dist/adapters/evm/rpc.js.map +1 -0
- package/dist/adapters/evm/tokens.d.ts +7 -0
- package/dist/adapters/evm/tokens.js +23 -0
- package/dist/adapters/evm/tokens.js.map +1 -0
- package/dist/adapters/evm/types.d.ts +255 -0
- package/dist/{type/account.js → adapters/evm/types.js} +1 -1
- package/dist/adapters/evm/types.js.map +1 -0
- package/dist/adapters/evm/web3-client.d.ts +23 -0
- package/dist/adapters/evm/web3-client.js +159 -0
- package/dist/adapters/evm/web3-client.js.map +1 -0
- package/dist/adapters/solana/builder.d.ts +18 -0
- package/dist/adapters/solana/builder.js +545 -0
- package/dist/adapters/solana/builder.js.map +1 -0
- package/dist/adapters/solana/chains.d.ts +13 -0
- package/dist/adapters/solana/chains.js +37 -0
- package/dist/adapters/solana/chains.js.map +1 -0
- package/dist/adapters/solana/decode.d.ts +111 -0
- package/dist/adapters/solana/decode.js +595 -0
- package/dist/adapters/solana/decode.js.map +1 -0
- package/dist/adapters/solana/driver.d.ts +15 -0
- package/dist/adapters/solana/driver.js +72 -0
- package/dist/adapters/solana/driver.js.map +1 -0
- package/dist/adapters/solana/errors.d.ts +36 -0
- package/dist/adapters/solana/errors.js +154 -0
- package/dist/adapters/solana/errors.js.map +1 -0
- package/dist/adapters/solana/fees.d.ts +68 -0
- package/dist/adapters/solana/fees.js +205 -0
- package/dist/adapters/solana/fees.js.map +1 -0
- package/dist/adapters/solana/heights.d.ts +47 -0
- package/dist/adapters/solana/heights.js +185 -0
- package/dist/adapters/solana/heights.js.map +1 -0
- package/dist/adapters/solana/history.d.ts +10 -0
- package/dist/adapters/solana/history.js +71 -0
- package/dist/adapters/solana/history.js.map +1 -0
- package/dist/adapters/solana/index.d.ts +16 -0
- package/dist/adapters/solana/index.js +9 -0
- package/dist/adapters/solana/index.js.map +1 -0
- package/dist/adapters/solana/keys.d.ts +13 -0
- package/dist/adapters/solana/keys.js +69 -0
- package/dist/adapters/solana/keys.js.map +1 -0
- package/dist/adapters/solana/network.d.ts +24 -0
- package/dist/adapters/solana/network.js +95 -0
- package/dist/adapters/solana/network.js.map +1 -0
- package/dist/adapters/solana/plugin.d.ts +18 -0
- package/dist/adapters/solana/plugin.js +41 -0
- package/dist/adapters/solana/plugin.js.map +1 -0
- package/dist/adapters/solana/presets.d.ts +2 -0
- package/dist/adapters/solana/presets.js +77 -0
- package/dist/adapters/solana/presets.js.map +1 -0
- package/dist/adapters/solana/programs.d.ts +44 -0
- package/dist/adapters/solana/programs.js +159 -0
- package/dist/adapters/solana/programs.js.map +1 -0
- package/dist/adapters/solana/proofs.d.ts +56 -0
- package/dist/adapters/solana/proofs.js +540 -0
- package/dist/adapters/solana/proofs.js.map +1 -0
- package/dist/adapters/solana/reader.d.ts +82 -0
- package/dist/adapters/solana/reader.js +326 -0
- package/dist/adapters/solana/reader.js.map +1 -0
- package/dist/adapters/solana/rpc.d.ts +102 -0
- package/dist/adapters/solana/rpc.js +301 -0
- package/dist/adapters/solana/rpc.js.map +1 -0
- package/dist/adapters/solana/tokens.d.ts +7 -0
- package/dist/adapters/solana/tokens.js +19 -0
- package/dist/adapters/solana/tokens.js.map +1 -0
- package/dist/adapters/solana/types.d.ts +121 -0
- package/dist/{type/lib-types.js → adapters/solana/types.js} +1 -1
- package/dist/adapters/solana/types.js.map +1 -0
- package/dist/adapters/solana/web3.d.ts +5 -0
- package/dist/adapters/solana/web3.js +83 -0
- package/dist/adapters/solana/web3.js.map +1 -0
- package/dist/adapters/solana/wire.d.ts +62 -0
- package/dist/adapters/solana/wire.js +168 -0
- package/dist/adapters/solana/wire.js.map +1 -0
- package/dist/adapters/ton/address.d.ts +43 -0
- package/dist/adapters/ton/address.js +168 -0
- package/dist/adapters/ton/address.js.map +1 -0
- package/dist/adapters/ton/api.d.ts +344 -0
- package/dist/adapters/ton/api.js +942 -0
- package/dist/adapters/ton/api.js.map +1 -0
- package/dist/adapters/ton/builder.d.ts +18 -0
- package/dist/adapters/ton/builder.js +701 -0
- package/dist/adapters/ton/builder.js.map +1 -0
- package/dist/adapters/ton/chains.d.ts +16 -0
- package/dist/adapters/ton/chains.js +39 -0
- package/dist/adapters/ton/chains.js.map +1 -0
- package/dist/adapters/ton/decode.d.ts +43 -0
- package/dist/adapters/ton/decode.js +219 -0
- package/dist/adapters/ton/decode.js.map +1 -0
- package/dist/adapters/ton/driver.d.ts +10 -0
- package/dist/adapters/ton/driver.js +117 -0
- package/dist/adapters/ton/driver.js.map +1 -0
- package/dist/adapters/ton/errors.d.ts +36 -0
- package/dist/adapters/ton/errors.js +89 -0
- package/dist/adapters/ton/errors.js.map +1 -0
- package/dist/adapters/ton/fees.d.ts +28 -0
- package/dist/adapters/ton/fees.js +121 -0
- package/dist/adapters/ton/fees.js.map +1 -0
- package/dist/adapters/ton/index.d.ts +16 -0
- package/dist/adapters/ton/index.js +9 -0
- package/dist/adapters/ton/index.js.map +1 -0
- package/dist/adapters/ton/messages.d.ts +157 -0
- package/dist/adapters/ton/messages.js +397 -0
- package/dist/adapters/ton/messages.js.map +1 -0
- package/dist/adapters/ton/native-client.d.ts +10 -0
- package/dist/adapters/ton/native-client.js +47 -0
- package/dist/adapters/ton/native-client.js.map +1 -0
- package/dist/adapters/ton/network.d.ts +58 -0
- package/dist/adapters/ton/network.js +207 -0
- package/dist/adapters/ton/network.js.map +1 -0
- package/dist/adapters/ton/plugin.d.ts +24 -0
- package/dist/adapters/ton/plugin.js +57 -0
- package/dist/adapters/ton/plugin.js.map +1 -0
- package/dist/adapters/ton/presets.d.ts +6 -0
- package/dist/adapters/ton/presets.js +94 -0
- package/dist/adapters/ton/presets.js.map +1 -0
- package/dist/adapters/ton/proofs.d.ts +66 -0
- package/dist/adapters/ton/proofs.js +813 -0
- package/dist/adapters/ton/proofs.js.map +1 -0
- package/dist/adapters/ton/reader.d.ts +194 -0
- package/dist/adapters/ton/reader.js +781 -0
- package/dist/adapters/ton/reader.js.map +1 -0
- package/dist/adapters/ton/tokens.d.ts +10 -0
- package/dist/adapters/ton/tokens.js +27 -0
- package/dist/adapters/ton/tokens.js.map +1 -0
- package/dist/adapters/ton/trace.d.ts +48 -0
- package/dist/adapters/ton/trace.js +277 -0
- package/dist/adapters/ton/trace.js.map +1 -0
- package/dist/adapters/ton/types.d.ts +105 -0
- package/dist/adapters/ton/types.js +3 -0
- package/dist/adapters/ton/types.js.map +1 -0
- package/dist/adapters/ton/wallets.d.ts +86 -0
- package/dist/adapters/ton/wallets.js +373 -0
- package/dist/adapters/ton/wallets.js.map +1 -0
- package/dist/adapters/tron/abi.d.ts +39 -0
- package/dist/adapters/tron/abi.js +110 -0
- package/dist/adapters/tron/abi.js.map +1 -0
- package/dist/adapters/tron/address.d.ts +20 -0
- package/dist/adapters/tron/address.js +110 -0
- package/dist/adapters/tron/address.js.map +1 -0
- package/dist/adapters/tron/builder.d.ts +12 -0
- package/dist/adapters/tron/builder.js +553 -0
- package/dist/adapters/tron/builder.js.map +1 -0
- package/dist/adapters/tron/chains.d.ts +12 -0
- package/dist/adapters/tron/chains.js +35 -0
- package/dist/adapters/tron/chains.js.map +1 -0
- package/dist/adapters/tron/codec.d.ts +10 -0
- package/dist/adapters/tron/codec.js +322 -0
- package/dist/adapters/tron/codec.js.map +1 -0
- package/dist/adapters/tron/decode.d.ts +50 -0
- package/dist/adapters/tron/decode.js +280 -0
- package/dist/adapters/tron/decode.js.map +1 -0
- package/dist/adapters/tron/driver.d.ts +12 -0
- package/dist/adapters/tron/driver.js +106 -0
- package/dist/adapters/tron/driver.js.map +1 -0
- package/dist/adapters/tron/errors.d.ts +74 -0
- package/dist/adapters/tron/errors.js +261 -0
- package/dist/adapters/tron/errors.js.map +1 -0
- package/dist/adapters/tron/fees.d.ts +49 -0
- package/dist/adapters/tron/fees.js +166 -0
- package/dist/adapters/tron/fees.js.map +1 -0
- package/dist/adapters/tron/http.d.ts +173 -0
- package/dist/adapters/tron/http.js +729 -0
- package/dist/adapters/tron/http.js.map +1 -0
- package/dist/adapters/tron/index.d.ts +16 -0
- package/dist/adapters/tron/index.js +15 -0
- package/dist/adapters/tron/index.js.map +1 -0
- package/dist/adapters/tron/network.d.ts +44 -0
- package/dist/adapters/tron/network.js +163 -0
- package/dist/adapters/tron/network.js.map +1 -0
- package/dist/adapters/tron/plugin.d.ts +17 -0
- package/dist/adapters/tron/plugin.js +39 -0
- package/dist/adapters/tron/plugin.js.map +1 -0
- package/dist/adapters/tron/presets.d.ts +5 -0
- package/dist/adapters/tron/presets.js +68 -0
- package/dist/adapters/tron/presets.js.map +1 -0
- package/dist/adapters/tron/proofs.d.ts +80 -0
- package/dist/adapters/tron/proofs.js +370 -0
- package/dist/adapters/tron/proofs.js.map +1 -0
- package/dist/adapters/tron/protobuf.d.ts +36 -0
- package/dist/adapters/tron/protobuf.js +90 -0
- package/dist/adapters/tron/protobuf.js.map +1 -0
- package/dist/adapters/tron/reader.d.ts +47 -0
- package/dist/adapters/tron/reader.js +203 -0
- package/dist/adapters/tron/reader.js.map +1 -0
- package/dist/adapters/tron/tokens.d.ts +7 -0
- package/dist/adapters/tron/tokens.js +14 -0
- package/dist/adapters/tron/tokens.js.map +1 -0
- package/dist/adapters/tron/types.d.ts +166 -0
- package/dist/adapters/tron/types.js +3 -0
- package/dist/adapters/tron/types.js.map +1 -0
- package/dist/adapters/utxo/address.d.ts +51 -0
- package/dist/adapters/utxo/address.js +341 -0
- package/dist/adapters/utxo/address.js.map +1 -0
- package/dist/adapters/utxo/builder.d.ts +35 -0
- package/dist/adapters/utxo/builder.js +380 -0
- package/dist/adapters/utxo/builder.js.map +1 -0
- package/dist/adapters/utxo/chains.d.ts +17 -0
- package/dist/adapters/utxo/chains.js +99 -0
- package/dist/adapters/utxo/chains.js.map +1 -0
- package/dist/adapters/utxo/codec.d.ts +120 -0
- package/dist/adapters/utxo/codec.js +408 -0
- package/dist/adapters/utxo/codec.js.map +1 -0
- package/dist/adapters/utxo/coinselect.d.ts +48 -0
- package/dist/adapters/utxo/coinselect.js +131 -0
- package/dist/adapters/utxo/coinselect.js.map +1 -0
- package/dist/adapters/utxo/context.d.ts +57 -0
- package/dist/adapters/utxo/context.js +118 -0
- package/dist/adapters/utxo/context.js.map +1 -0
- package/dist/adapters/utxo/decode.d.ts +14 -0
- package/dist/adapters/utxo/decode.js +85 -0
- package/dist/adapters/utxo/decode.js.map +1 -0
- package/dist/adapters/utxo/driver.d.ts +16 -0
- package/dist/adapters/utxo/driver.js +74 -0
- package/dist/adapters/utxo/driver.js.map +1 -0
- package/dist/adapters/utxo/ecc.d.ts +9 -0
- package/dist/adapters/utxo/ecc.js +26 -0
- package/dist/adapters/utxo/ecc.js.map +1 -0
- package/dist/adapters/utxo/errors.d.ts +52 -0
- package/dist/adapters/utxo/errors.js +191 -0
- package/dist/adapters/utxo/errors.js.map +1 -0
- package/dist/adapters/utxo/esplora.d.ts +79 -0
- package/dist/adapters/utxo/esplora.js +451 -0
- package/dist/adapters/utxo/esplora.js.map +1 -0
- package/dist/adapters/utxo/fees.d.ts +41 -0
- package/dist/adapters/utxo/fees.js +125 -0
- package/dist/adapters/utxo/fees.js.map +1 -0
- package/dist/adapters/utxo/index.d.ts +17 -0
- package/dist/adapters/utxo/index.js +8 -0
- package/dist/adapters/utxo/index.js.map +1 -0
- package/dist/adapters/utxo/network.d.ts +50 -0
- package/dist/adapters/utxo/network.js +165 -0
- package/dist/adapters/utxo/network.js.map +1 -0
- package/dist/adapters/utxo/plugin.d.ts +17 -0
- package/dist/adapters/utxo/plugin.js +41 -0
- package/dist/adapters/utxo/plugin.js.map +1 -0
- package/dist/adapters/utxo/presets.d.ts +12 -0
- package/dist/adapters/utxo/presets.js +47 -0
- package/dist/adapters/utxo/presets.js.map +1 -0
- package/dist/adapters/utxo/preview.d.ts +3 -0
- package/dist/adapters/utxo/preview.js +65 -0
- package/dist/adapters/utxo/preview.js.map +1 -0
- package/dist/adapters/utxo/proofs.d.ts +57 -0
- package/dist/adapters/utxo/proofs.js +331 -0
- package/dist/adapters/utxo/proofs.js.map +1 -0
- package/dist/adapters/utxo/rawtx.d.ts +59 -0
- package/dist/adapters/utxo/rawtx.js +234 -0
- package/dist/adapters/utxo/rawtx.js.map +1 -0
- package/dist/adapters/utxo/reader.d.ts +36 -0
- package/dist/adapters/utxo/reader.js +265 -0
- package/dist/adapters/utxo/reader.js.map +1 -0
- package/dist/adapters/utxo/sdk.d.ts +18 -0
- package/dist/adapters/utxo/sdk.js +17 -0
- package/dist/adapters/utxo/sdk.js.map +1 -0
- package/dist/adapters/utxo/signed-psbt.d.ts +36 -0
- package/dist/adapters/utxo/signed-psbt.js +428 -0
- package/dist/adapters/utxo/signed-psbt.js.map +1 -0
- package/dist/adapters/utxo/spend.d.ts +59 -0
- package/dist/adapters/utxo/spend.js +230 -0
- package/dist/adapters/utxo/spend.js.map +1 -0
- package/dist/adapters/utxo/types.d.ts +167 -0
- package/dist/adapters/utxo/types.js +3 -0
- package/dist/adapters/utxo/types.js.map +1 -0
- package/dist/core/assets/service.d.ts +18 -0
- package/dist/core/assets/service.js +69 -0
- package/dist/core/assets/service.js.map +1 -0
- package/dist/core/blockchain/default-ref.d.ts +4 -0
- package/dist/core/blockchain/default-ref.js +16 -0
- package/dist/core/blockchain/default-ref.js.map +1 -0
- package/dist/core/blockchain/handle.d.ts +200 -0
- package/dist/core/blockchain/handle.js +579 -0
- package/dist/core/blockchain/handle.js.map +1 -0
- package/dist/core/blockchain/internal.d.ts +19 -0
- package/dist/core/blockchain/internal.js +16 -0
- package/dist/core/blockchain/internal.js.map +1 -0
- package/dist/core/blockchain/mapping.d.ts +22 -0
- package/dist/core/blockchain/mapping.js +136 -0
- package/dist/core/blockchain/mapping.js.map +1 -0
- package/dist/core/config/env.d.ts +8 -0
- package/dist/core/config/env.js +60 -0
- package/dist/core/config/env.js.map +1 -0
- package/dist/core/config/merge.d.ts +26 -0
- package/dist/core/config/merge.js +144 -0
- package/dist/core/config/merge.js.map +1 -0
- package/dist/core/config/resolve.d.ts +12 -0
- package/dist/core/config/resolve.js +251 -0
- package/dist/core/config/resolve.js.map +1 -0
- package/dist/core/config/types.d.ts +165 -0
- package/dist/core/config/types.js +3 -0
- package/dist/core/config/types.js.map +1 -0
- package/dist/core/container/builtins.d.ts +4 -0
- package/dist/core/container/builtins.js +13 -0
- package/dist/core/container/builtins.js.map +1 -0
- package/dist/core/container/container.d.ts +69 -0
- package/dist/core/container/container.js +466 -0
- package/dist/core/container/container.js.map +1 -0
- package/dist/core/container/default.d.ts +15 -0
- package/dist/core/container/default.js +70 -0
- package/dist/core/container/default.js.map +1 -0
- package/dist/core/container/internals.d.ts +54 -0
- package/dist/core/container/internals.js +21 -0
- package/dist/core/container/internals.js.map +1 -0
- package/dist/core/container/pool.d.ts +27 -0
- package/dist/core/container/pool.js +77 -0
- package/dist/core/container/pool.js.map +1 -0
- package/dist/core/driver/types.d.ts +346 -0
- package/dist/core/driver/types.js +3 -0
- package/dist/core/driver/types.js.map +1 -0
- package/dist/core/errors/codes.d.ts +153 -0
- package/dist/core/errors/codes.js +49 -0
- package/dist/core/errors/codes.js.map +1 -0
- package/dist/core/errors/error.d.ts +66 -0
- package/dist/core/errors/error.js +129 -0
- package/dist/core/errors/error.js.map +1 -0
- package/dist/core/events/bus.d.ts +12 -0
- package/dist/core/events/bus.js +46 -0
- package/dist/core/events/bus.js.map +1 -0
- package/dist/core/events/logger.d.ts +13 -0
- package/dist/core/events/logger.js +42 -0
- package/dist/core/events/logger.js.map +1 -0
- package/dist/core/events/types.d.ts +131 -0
- package/dist/core/events/types.js +3 -0
- package/dist/core/events/types.js.map +1 -0
- package/dist/core/lifecycle/engine-rules.d.ts +107 -0
- package/dist/core/lifecycle/engine-rules.js +257 -0
- package/dist/core/lifecycle/engine-rules.js.map +1 -0
- package/dist/core/lifecycle/engine.d.ts +500 -0
- package/dist/core/lifecycle/engine.js +1732 -0
- package/dist/core/lifecycle/engine.js.map +1 -0
- package/dist/core/lifecycle/evaluate.d.ts +19 -0
- package/dist/core/lifecycle/evaluate.js +72 -0
- package/dist/core/lifecycle/evaluate.js.map +1 -0
- package/dist/core/lifecycle/intent.d.ts +11 -0
- package/dist/core/lifecycle/intent.js +88 -0
- package/dist/core/lifecycle/intent.js.map +1 -0
- package/dist/core/lifecycle/monitor.d.ts +138 -0
- package/dist/core/lifecycle/monitor.js +606 -0
- package/dist/core/lifecycle/monitor.js.map +1 -0
- package/dist/core/lifecycle/observations.d.ts +17 -0
- package/dist/core/lifecycle/observations.js +59 -0
- package/dist/core/lifecycle/observations.js.map +1 -0
- package/dist/core/lifecycle/reconcile.d.ts +58 -0
- package/dist/core/lifecycle/reconcile.js +112 -0
- package/dist/core/lifecycle/reconcile.js.map +1 -0
- package/dist/core/lifecycle/views.d.ts +49 -0
- package/dist/core/lifecycle/views.js +57 -0
- package/dist/core/lifecycle/views.js.map +1 -0
- package/dist/core/lifecycle/workers.d.ts +82 -0
- package/dist/core/lifecycle/workers.js +329 -0
- package/dist/core/lifecycle/workers.js.map +1 -0
- package/dist/core/model/address.d.ts +32 -0
- package/dist/core/model/address.js +43 -0
- package/dist/core/model/address.js.map +1 -0
- package/dist/core/model/amount.d.ts +25 -0
- package/dist/core/model/amount.js +102 -0
- package/dist/core/model/amount.js.map +1 -0
- package/dist/core/model/asset.d.ts +28 -0
- package/dist/core/model/asset.js +47 -0
- package/dist/core/model/asset.js.map +1 -0
- package/dist/core/model/capability.d.ts +3 -0
- package/dist/core/model/capability.js +18 -0
- package/dist/core/model/capability.js.map +1 -0
- package/dist/core/model/chain.d.ts +63 -0
- package/dist/core/model/chain.js +8 -0
- package/dist/core/model/chain.js.map +1 -0
- package/dist/core/model/fee.d.ts +36 -0
- package/dist/core/model/fee.js +17 -0
- package/dist/core/model/fee.js.map +1 -0
- package/dist/core/model/ids.d.ts +37 -0
- package/dist/core/model/ids.js +13 -0
- package/dist/core/model/ids.js.map +1 -0
- package/dist/core/model/intent.d.ts +63 -0
- package/dist/core/model/intent.js +81 -0
- package/dist/core/model/intent.js.map +1 -0
- package/dist/core/model/ordering.d.ts +20 -0
- package/dist/core/model/ordering.js +29 -0
- package/dist/core/model/ordering.js.map +1 -0
- package/dist/core/model/transaction.d.ts +116 -0
- package/dist/core/model/transaction.js +3 -0
- package/dist/core/model/transaction.js.map +1 -0
- package/dist/core/observe/scanner.d.ts +135 -0
- package/dist/core/observe/scanner.js +355 -0
- package/dist/core/observe/scanner.js.map +1 -0
- package/dist/core/ordering/reservations.d.ts +16 -0
- package/dist/core/ordering/reservations.js +53 -0
- package/dist/core/ordering/reservations.js.map +1 -0
- package/dist/core/ordering/sequence.d.ts +61 -0
- package/dist/core/ordering/sequence.js +155 -0
- package/dist/core/ordering/sequence.js.map +1 -0
- package/dist/core/registry/adapters.d.ts +10 -0
- package/dist/core/registry/adapters.js +56 -0
- package/dist/core/registry/adapters.js.map +1 -0
- package/dist/core/registry/assets.d.ts +18 -0
- package/dist/core/registry/assets.js +90 -0
- package/dist/core/registry/assets.js.map +1 -0
- package/dist/core/registry/chains.d.ts +10 -0
- package/dist/core/registry/chains.js +80 -0
- package/dist/core/registry/chains.js.map +1 -0
- package/dist/core/registry/plugin.d.ts +41 -0
- package/dist/core/registry/plugin.js +109 -0
- package/dist/core/registry/plugin.js.map +1 -0
- package/dist/core/registry/providers.d.ts +31 -0
- package/dist/core/registry/providers.js +43 -0
- package/dist/core/registry/providers.js.map +1 -0
- package/dist/core/registry/schemes.d.ts +30 -0
- package/dist/core/registry/schemes.js +84 -0
- package/dist/core/registry/schemes.js.map +1 -0
- package/dist/core/secret/fragments.d.ts +33 -0
- package/dist/core/secret/fragments.js +110 -0
- package/dist/core/secret/fragments.js.map +1 -0
- package/dist/core/secret/redact.d.ts +10 -0
- package/dist/core/secret/redact.js +110 -0
- package/dist/core/secret/redact.js.map +1 -0
- package/dist/core/secret/secret.d.ts +14 -0
- package/dist/core/secret/secret.js +42 -0
- package/dist/core/secret/secret.js.map +1 -0
- package/dist/core/signing/callback.d.ts +10 -0
- package/dist/core/signing/callback.js +22 -0
- package/dist/core/signing/callback.js.map +1 -0
- package/dist/core/signing/guard.d.ts +18 -0
- package/dist/core/signing/guard.js +72 -0
- package/dist/core/signing/guard.js.map +1 -0
- package/dist/core/signing/hd.d.ts +36 -0
- package/dist/core/signing/hd.js +167 -0
- package/dist/core/signing/hd.js.map +1 -0
- package/dist/core/signing/local.d.ts +48 -0
- package/dist/core/signing/local.js +190 -0
- package/dist/core/signing/local.js.map +1 -0
- package/dist/core/signing/orchestrator.d.ts +40 -0
- package/dist/core/signing/orchestrator.js +300 -0
- package/dist/core/signing/orchestrator.js.map +1 -0
- package/dist/core/signing/types.d.ts +64 -0
- package/dist/core/signing/types.js +3 -0
- package/dist/core/signing/types.js.map +1 -0
- package/dist/core/signing/wallet.d.ts +48 -0
- package/dist/core/signing/wallet.js +153 -0
- package/dist/core/signing/wallet.js.map +1 -0
- package/dist/core/store/clone.d.ts +25 -0
- package/dist/core/store/clone.js +71 -0
- package/dist/core/store/clone.js.map +1 -0
- package/dist/core/store/memory.d.ts +38 -0
- package/dist/core/store/memory.js +325 -0
- package/dist/core/store/memory.js.map +1 -0
- package/dist/core/store/types.d.ts +246 -0
- package/dist/core/store/types.js +117 -0
- package/dist/core/store/types.js.map +1 -0
- package/dist/core/transport/backoff.d.ts +8 -0
- package/dist/core/transport/backoff.js +27 -0
- package/dist/core/transport/backoff.js.map +1 -0
- package/dist/core/transport/circuit.d.ts +25 -0
- package/dist/core/transport/circuit.js +61 -0
- package/dist/core/transport/circuit.js.map +1 -0
- package/dist/core/transport/http-transport.d.ts +30 -0
- package/dist/core/transport/http-transport.js +1695 -0
- package/dist/core/transport/http-transport.js.map +1 -0
- package/dist/core/transport/rate-limit.d.ts +27 -0
- package/dist/core/transport/rate-limit.js +78 -0
- package/dist/core/transport/rate-limit.js.map +1 -0
- package/dist/core/transport/stale-view.d.ts +11 -0
- package/dist/core/transport/stale-view.js +17 -0
- package/dist/core/transport/stale-view.js.map +1 -0
- package/dist/core/transport/types.d.ts +144 -0
- package/dist/core/transport/types.js +6 -0
- package/dist/core/transport/types.js.map +1 -0
- package/dist/core/util/bytes.d.ts +9 -0
- package/dist/core/util/bytes.js +40 -0
- package/dist/core/util/bytes.js.map +1 -0
- package/dist/core/util/clock.d.ts +6 -0
- package/dist/core/util/clock.js +26 -0
- package/dist/core/util/clock.js.map +1 -0
- package/dist/core/util/freeze.d.ts +8 -0
- package/dist/core/util/freeze.js +31 -0
- package/dist/core/util/freeze.js.map +1 -0
- package/dist/core/util/json.d.ts +29 -0
- package/dist/core/util/json.js +165 -0
- package/dist/core/util/json.js.map +1 -0
- package/dist/core/util/names.d.ts +21 -0
- package/dist/core/util/names.js +46 -0
- package/dist/core/util/names.js.map +1 -0
- package/dist/index.d.ts +64 -14
- package/dist/index.js +105 -49
- package/dist/index.js.map +1 -1
- package/dist/native.d.ts +21 -0
- package/dist/native.js +44 -0
- package/dist/native.js.map +1 -0
- package/dist/testing/contracts/api.d.ts +12 -0
- package/dist/testing/contracts/api.js +58 -0
- package/dist/testing/contracts/api.js.map +1 -0
- package/dist/testing/contracts/cursors.d.ts +6 -0
- package/dist/testing/contracts/cursors.js +43 -0
- package/dist/testing/contracts/cursors.js.map +1 -0
- package/dist/testing/contracts/locks.d.ts +10 -0
- package/dist/testing/contracts/locks.js +63 -0
- package/dist/testing/contracts/locks.js.map +1 -0
- package/dist/testing/contracts/operations.d.ts +21 -0
- package/dist/testing/contracts/operations.js +718 -0
- package/dist/testing/contracts/operations.js.map +1 -0
- package/dist/testing/contracts/sequences.d.ts +6 -0
- package/dist/testing/contracts/sequences.js +68 -0
- package/dist/testing/contracts/sequences.js.map +1 -0
- package/dist/testing/env.d.ts +63 -0
- package/dist/testing/env.js +105 -0
- package/dist/testing/env.js.map +1 -0
- package/dist/testing/fake-chain.d.ts +118 -0
- package/dist/testing/fake-chain.js +536 -0
- package/dist/testing/fake-chain.js.map +1 -0
- package/dist/testing/fake-clock.d.ts +15 -0
- package/dist/testing/fake-clock.js +86 -0
- package/dist/testing/fake-clock.js.map +1 -0
- package/dist/testing/fake-driver.d.ts +15 -0
- package/dist/testing/fake-driver.js +458 -0
- package/dist/testing/fake-driver.js.map +1 -0
- package/dist/testing/fake-fetch.d.ts +32 -0
- package/dist/testing/fake-fetch.js +81 -0
- package/dist/testing/fake-fetch.js.map +1 -0
- package/dist/testing/fake-plugin.d.ts +30 -0
- package/dist/testing/fake-plugin.js +66 -0
- package/dist/testing/fake-plugin.js.map +1 -0
- package/dist/testing/faulty-store.d.ts +36 -0
- package/dist/testing/faulty-store.js +66 -0
- package/dist/testing/faulty-store.js.map +1 -0
- package/dist/testing/generation.d.ts +60 -0
- package/dist/testing/generation.js +252 -0
- package/dist/testing/generation.js.map +1 -0
- package/dist/testing/index.d.ts +28 -0
- package/dist/testing/index.js +51 -0
- package/dist/testing/index.js.map +1 -0
- package/package.json +188 -44
- package/dist/libs/eth/account.d.ts +0 -9
- package/dist/libs/eth/account.js +0 -58
- package/dist/libs/eth/account.js.map +0 -1
- package/dist/libs/eth/contract.d.ts +0 -2
- package/dist/libs/eth/contract.js +0 -7
- package/dist/libs/eth/contract.js.map +0 -1
- package/dist/libs/eth/index.d.ts +0 -20
- package/dist/libs/eth/index.js +0 -62
- package/dist/libs/eth/index.js.map +0 -1
- package/dist/libs/eth/transact.d.ts +0 -2
- package/dist/libs/eth/transact.js +0 -7
- package/dist/libs/eth/transact.js.map +0 -1
- package/dist/libs/index.d.ts +0 -1
- package/dist/libs/index.js +0 -18
- package/dist/libs/index.js.map +0 -1
- package/dist/tool/common.d.ts +0 -28
- package/dist/tool/common.js +0 -33
- package/dist/tool/common.js.map +0 -1
- package/dist/tool/eth-tools.d.ts +0 -3
- package/dist/tool/eth-tools.js +0 -33
- package/dist/tool/eth-tools.js.map +0 -1
- package/dist/tool/index.d.ts +0 -4
- package/dist/tool/index.js +0 -21
- package/dist/tool/index.js.map +0 -1
- package/dist/tool/logging.d.ts +0 -3
- package/dist/tool/logging.js +0 -11
- package/dist/tool/logging.js.map +0 -1
- package/dist/tool/options.d.ts +0 -4
- package/dist/tool/options.js +0 -28
- package/dist/tool/options.js.map +0 -1
- package/dist/type/account.d.ts +0 -9
- package/dist/type/account.js.map +0 -1
- package/dist/type/common.d.ts +0 -18
- package/dist/type/common.js.map +0 -1
- package/dist/type/index.d.ts +0 -3
- package/dist/type/index.js +0 -20
- package/dist/type/index.js.map +0 -1
- package/dist/type/lib-types.d.ts +0 -7
- package/dist/type/lib-types.js.map +0 -1
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Workers = void 0;
|
|
4
|
+
const error_1 = require("../errors/error");
|
|
5
|
+
const types_1 = require("../store/types");
|
|
6
|
+
const bytes_1 = require("../util/bytes");
|
|
7
|
+
const engine_rules_1 = require("./engine-rules");
|
|
8
|
+
const DEFAULT_BATCH = 50;
|
|
9
|
+
/** How many Operations' reported gaps a monitor remembers (`nonce.gap` is at-least-once). */
|
|
10
|
+
const GAP_MEMORY = 10_000;
|
|
11
|
+
/** Worker passes and startup recovery for one monitor (see `Monitor`). */
|
|
12
|
+
class Workers {
|
|
13
|
+
deps;
|
|
14
|
+
monitor;
|
|
15
|
+
/**
|
|
16
|
+
* Per Operation, the expected nonces a `nonce.gap` was already emitted for; least
|
|
17
|
+
* recently reported first, capped at `GAP_MEMORY` Operations.
|
|
18
|
+
*/
|
|
19
|
+
#gaps = new Map();
|
|
20
|
+
constructor(deps, monitor) {
|
|
21
|
+
this.deps = deps;
|
|
22
|
+
this.monitor = monitor;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* One worker pass: claims up to `batch` due Operations, checks each under its claim fence
|
|
26
|
+
* (a stale worker's writes fail), then releases the claim. Every claimed Operation
|
|
27
|
+
* that stays live leaves the pass scheduled a poll interval ahead, including when its
|
|
28
|
+
* check threw, its view was stale or its all-rejected verdict could not run, so no worker
|
|
29
|
+
* claims it again before then. A stale view also skips gap handling and reconciliation.
|
|
30
|
+
* `signal` bounds each check and its lease wait; once it aborts, the Operations not yet
|
|
31
|
+
* checked are only released, still due, for another worker. Returns how many Operations
|
|
32
|
+
* it claimed.
|
|
33
|
+
*/
|
|
34
|
+
async runOnce(options) {
|
|
35
|
+
const { signal } = options;
|
|
36
|
+
if (signal?.aborted)
|
|
37
|
+
return 0;
|
|
38
|
+
const claimed = await this.deps.stores.operations.claimDue(this.deps.namespace, options.workerId, this.deps.clock.now(), this.deps.lifecycle().claimLeaseMs, options.batch ?? DEFAULT_BATCH);
|
|
39
|
+
const reads = this.#passResolver(this.deps.resolveRead);
|
|
40
|
+
const writes = this.#passResolver(this.deps.resolveTarget);
|
|
41
|
+
for (const op of claimed) {
|
|
42
|
+
const fence = { claimToken: op.claim.token };
|
|
43
|
+
if (!signal?.aborted)
|
|
44
|
+
await this.#process(reads, writes, op, fence, signal);
|
|
45
|
+
await this.deps.stores.operations
|
|
46
|
+
.releaseClaim(this.deps.namespace, op.id, fence)
|
|
47
|
+
.catch((error) => this.deps.log.debug('claim already lost', {
|
|
48
|
+
operationId: op.id,
|
|
49
|
+
code: (0, engine_rules_1.errorCode)(error),
|
|
50
|
+
}));
|
|
51
|
+
}
|
|
52
|
+
return claimed.length;
|
|
53
|
+
}
|
|
54
|
+
/** One claimed Operation of a worker pass (see `runOnce`). */
|
|
55
|
+
async #process(reads, writes, op, fence, signal) {
|
|
56
|
+
const started = this.deps.clock.now();
|
|
57
|
+
let current;
|
|
58
|
+
try {
|
|
59
|
+
const target = await this.#resolved(reads, op);
|
|
60
|
+
const pass = await this.monitor.checkPass(target, op, fence, signal);
|
|
61
|
+
current = pass.record;
|
|
62
|
+
if (!pass.stale)
|
|
63
|
+
await this.#detectNonceGap(target, current, writes);
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
// An abort mid-check is an expected shutdown, not a failure.
|
|
67
|
+
this.deps.log[signal?.aborted ? 'debug' : 'warn'](signal?.aborted ? 'monitor check stopped' : 'monitor check failed', { operationId: op.id, code: (0, engine_rules_1.errorCode)(error) });
|
|
68
|
+
}
|
|
69
|
+
const scheduled = current !== undefined &&
|
|
70
|
+
((0, types_1.isTerminal)(current.state) ||
|
|
71
|
+
(current.nextCheckAt !== undefined && current.nextCheckAt > started));
|
|
72
|
+
if (!scheduled)
|
|
73
|
+
await this.#reschedule(op.id, fence, started);
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Runs worker passes until `signal` aborts. Any number of workers, in any number of
|
|
77
|
+
* processes, may run: claims keep them apart. A full batch is followed by the next pass at
|
|
78
|
+
* once, anything less by a poll-interval sleep. A failed pass (e.g. a store outage) is
|
|
79
|
+
* logged by code and retried after the sleep.
|
|
80
|
+
*/
|
|
81
|
+
async start(options = {}) {
|
|
82
|
+
const workerId = options.workerId ?? (0, bytes_1.randomId)('worker');
|
|
83
|
+
const batch = options.batch ?? DEFAULT_BATCH;
|
|
84
|
+
const { signal } = options;
|
|
85
|
+
while (!signal?.aborted) {
|
|
86
|
+
let processed = 0;
|
|
87
|
+
try {
|
|
88
|
+
processed = await this.runOnce({
|
|
89
|
+
workerId,
|
|
90
|
+
batch,
|
|
91
|
+
...(signal ? { signal } : {}),
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
catch (error) {
|
|
95
|
+
this.deps.log.warn('monitor worker pass failed', {
|
|
96
|
+
workerId,
|
|
97
|
+
code: (0, engine_rules_1.errorCode)(error),
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
if (processed > 0 && processed >= batch)
|
|
101
|
+
continue;
|
|
102
|
+
try {
|
|
103
|
+
await this.deps.clock.sleep(this.deps.lifecycle().pollIntervalMs, signal);
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Startup recovery for this namespace; it never signs. `signed` and ambiguously
|
|
112
|
+
* `submitted` Operations resend their stored raw bytes; every other signed-or-later live
|
|
113
|
+
* Operation is checked. `created`, `prepared`, `awaiting-signature` and `stalled` ones need
|
|
114
|
+
* a caller and are reported through `recovery.skipped` (codes and states only). Then each
|
|
115
|
+
* wallet with a live Operation has its nonces reconciled under its address lease. A
|
|
116
|
+
* failure is logged by code and counted, and the rest go on. `signal` stops recovery
|
|
117
|
+
* between Operations and bounds each check and lease wait. Known gap: a `signed` or
|
|
118
|
+
* ambiguous Operation whose wallet-bound target cannot be resolved is counted `failed`
|
|
119
|
+
* without its check, although the check needs no wallet.
|
|
120
|
+
*/
|
|
121
|
+
async recover(options = {}) {
|
|
122
|
+
const { signal } = options;
|
|
123
|
+
const { namespace } = this.deps;
|
|
124
|
+
const live = await this.deps.stores.operations.list({
|
|
125
|
+
namespace,
|
|
126
|
+
states: types_1.NON_TERMINAL_STATES,
|
|
127
|
+
});
|
|
128
|
+
const reads = this.#passResolver(this.deps.resolveRead);
|
|
129
|
+
const writes = this.#passResolver(this.deps.resolveTarget);
|
|
130
|
+
let rebroadcast = 0;
|
|
131
|
+
let checked = 0;
|
|
132
|
+
let skipped = 0;
|
|
133
|
+
let failed = 0;
|
|
134
|
+
let reconciled = 0;
|
|
135
|
+
const skip = (op, reason) => {
|
|
136
|
+
skipped += 1;
|
|
137
|
+
this.deps.events.emit('recovery.skipped', {
|
|
138
|
+
namespace,
|
|
139
|
+
operationId: op.id,
|
|
140
|
+
state: op.state,
|
|
141
|
+
reason,
|
|
142
|
+
});
|
|
143
|
+
};
|
|
144
|
+
for (const op of live) {
|
|
145
|
+
if (signal?.aborted)
|
|
146
|
+
break;
|
|
147
|
+
if (engine_rules_1.PRE_SIGNING_STATES.has(op.state)) {
|
|
148
|
+
skip(op, 'CALLER_ACTION_REQUIRED');
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
if (op.state === 'stalled') {
|
|
152
|
+
skip(op, 'STALLED');
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
try {
|
|
156
|
+
const target = await this.#resolved(reads, op);
|
|
157
|
+
let current = op;
|
|
158
|
+
if (op.state === 'signed' ||
|
|
159
|
+
(op.state === 'submitted' && op.ambiguous === true)) {
|
|
160
|
+
const writer = await this.#resolved(writes, op);
|
|
161
|
+
try {
|
|
162
|
+
current = await this.deps.engine.rebroadcast(writer, op.id, signal);
|
|
163
|
+
}
|
|
164
|
+
catch (error) {
|
|
165
|
+
// A refusal or an unknown outcome is recorded on the Operation: check it next.
|
|
166
|
+
if (!(0, error_1.isCryptoAioError)(error) ||
|
|
167
|
+
(error.category !== 'chain' && error.ambiguous !== true))
|
|
168
|
+
throw error;
|
|
169
|
+
current = (await this.monitor.find(op.id)) ?? op;
|
|
170
|
+
}
|
|
171
|
+
rebroadcast += 1;
|
|
172
|
+
}
|
|
173
|
+
await this.monitor.check(target, current, undefined, signal);
|
|
174
|
+
checked += 1;
|
|
175
|
+
}
|
|
176
|
+
catch (error) {
|
|
177
|
+
failed += 1;
|
|
178
|
+
this.deps.log.warn('recovery of an operation failed', {
|
|
179
|
+
operationId: op.id,
|
|
180
|
+
code: (0, engine_rules_1.errorCode)(error),
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
const wallets = new Map();
|
|
185
|
+
for (const op of live) {
|
|
186
|
+
const key = [op.context.chain, op.context.network, op.intent.from].join('\n');
|
|
187
|
+
if (!wallets.has(key))
|
|
188
|
+
wallets.set(key, op);
|
|
189
|
+
}
|
|
190
|
+
for (const op of wallets.values()) {
|
|
191
|
+
if (signal?.aborted)
|
|
192
|
+
break;
|
|
193
|
+
try {
|
|
194
|
+
const writer = await this.#resolved(writes, op);
|
|
195
|
+
reconciled += (await this.deps.engine.reconcileNonces(writer, op, { signal }))
|
|
196
|
+
.length;
|
|
197
|
+
}
|
|
198
|
+
catch (error) {
|
|
199
|
+
this.deps.log.warn('nonce reconciliation failed', {
|
|
200
|
+
operationId: op.id,
|
|
201
|
+
code: (0, engine_rules_1.errorCode)(error),
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
return { rebroadcast, checked, skipped, failed, reconciled };
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* `resolve` for one pass: each execution context's target is rebuilt at most once, and
|
|
209
|
+
* only when first asked for (a wallet-bound one only by a write that needs it).
|
|
210
|
+
*/
|
|
211
|
+
#passResolver(resolve) {
|
|
212
|
+
const targets = new Map();
|
|
213
|
+
return (op) => {
|
|
214
|
+
let target = targets.get(op.context.configHash);
|
|
215
|
+
if (!target) {
|
|
216
|
+
target = resolve(op);
|
|
217
|
+
targets.set(op.context.configHash, target);
|
|
218
|
+
}
|
|
219
|
+
return target;
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
async #resolved(resolve, op) {
|
|
223
|
+
const target = await resolve(op);
|
|
224
|
+
if (!target) {
|
|
225
|
+
throw new error_1.ConfigError('CONFIG_INVALID', `the target of operation '${op.id}' cannot be rebuilt from its context`);
|
|
226
|
+
}
|
|
227
|
+
return target;
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Leaves a claimed, live Operation scheduled a poll interval ahead, unless it ended,
|
|
231
|
+
* another worker took it over or a writer scheduled it meanwhile. A pre-signing Operation
|
|
232
|
+
* is never scheduled (callers drive it), so it is unscheduled instead. Best effort.
|
|
233
|
+
*/
|
|
234
|
+
async #reschedule(id, fence, started) {
|
|
235
|
+
try {
|
|
236
|
+
for (let tries = 0; tries < 3; tries++) {
|
|
237
|
+
const fresh = await this.deps.stores.operations.get(this.deps.namespace, id);
|
|
238
|
+
if (!fresh ||
|
|
239
|
+
(0, types_1.isTerminal)(fresh.state) ||
|
|
240
|
+
fresh.claim?.token !== fence.claimToken ||
|
|
241
|
+
(fresh.nextCheckAt !== undefined && fresh.nextCheckAt > started))
|
|
242
|
+
return;
|
|
243
|
+
const patch = engine_rules_1.PRE_SIGNING_STATES.has(fresh.state)
|
|
244
|
+
? { clear: ['nextCheckAt'] }
|
|
245
|
+
: { nextCheckAt: this.deps.clock.now() + this.deps.lifecycle().pollIntervalMs };
|
|
246
|
+
try {
|
|
247
|
+
await this.deps.engine.update(fresh, patch, fence);
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
catch (error) {
|
|
251
|
+
if (!(0, error_1.isCryptoAioError)(error, 'VERSION_CONFLICT'))
|
|
252
|
+
throw error;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
catch (error) {
|
|
257
|
+
this.deps.log.debug('could not reschedule a claimed operation', {
|
|
258
|
+
operationId: id,
|
|
259
|
+
code: (0, engine_rules_1.errorCode)(error),
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* `nonce.gap`, once per (Operation, expected nonce): a `submitted` Operation has waited
|
|
265
|
+
* longer than `droppedGracePeriodMs` since its active Attempt was first seen or sent, and
|
|
266
|
+
* the chain's pending nonce is still below its own (a lower nonce is missing
|
|
267
|
+
* even from the mempool, so congestion alone is no gap). It names the live Operation
|
|
268
|
+
* holding the expected nonce, when one exists. Every such pass then reconciles the wallet's nonces, trying the lease
|
|
269
|
+
* once (never a filler transaction): a leaked value goes back for the next transfer.
|
|
270
|
+
* Only that write resolves the wallet-bound target (`writes`).
|
|
271
|
+
*/
|
|
272
|
+
async #detectNonceGap(target, op, writes) {
|
|
273
|
+
const { sequence } = target.pooled.driver;
|
|
274
|
+
if (op.state !== 'submitted' || op.reservation?.kind !== 'nonce' || !sequence) {
|
|
275
|
+
this.#gaps.delete(op.id);
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
const attempt = op.attempts.find((a) => a.id === op.activeAttemptId);
|
|
279
|
+
const observation = attempt
|
|
280
|
+
? await this.deps.stores.operations.getObservation(attempt.id)
|
|
281
|
+
: null;
|
|
282
|
+
// Not `lastBroadcastAt`, which every resend of a dropped Attempt refreshes.
|
|
283
|
+
const since = observation?.firstSeenAt ?? attempt?.createdAt ?? op.createdAt;
|
|
284
|
+
if (this.deps.clock.now() - since < this.deps.lifecycle().droppedGracePeriodMs)
|
|
285
|
+
return;
|
|
286
|
+
const expected = await sequence.pending(op.intent.from);
|
|
287
|
+
if (expected >= op.reservation.nonce)
|
|
288
|
+
return;
|
|
289
|
+
const reported = this.#gaps.get(op.id) ?? new Set();
|
|
290
|
+
this.#gaps.delete(op.id);
|
|
291
|
+
this.#gaps.set(op.id, reported);
|
|
292
|
+
if (this.#gaps.size > GAP_MEMORY) {
|
|
293
|
+
const oldest = this.#gaps.keys().next().value;
|
|
294
|
+
if (oldest !== undefined)
|
|
295
|
+
this.#gaps.delete(oldest);
|
|
296
|
+
}
|
|
297
|
+
if (!reported.has(expected.toString())) {
|
|
298
|
+
reported.add(expected.toString());
|
|
299
|
+
const blocking = (await this.deps.stores.operations.list({
|
|
300
|
+
namespace: this.deps.namespace,
|
|
301
|
+
chain: op.context.chain,
|
|
302
|
+
network: op.context.network,
|
|
303
|
+
from: op.intent.from,
|
|
304
|
+
states: types_1.NON_TERMINAL_STATES,
|
|
305
|
+
})).find((o) => o.reservation?.kind === 'nonce' && o.reservation.nonce === expected);
|
|
306
|
+
this.deps.events.emit('nonce.gap', {
|
|
307
|
+
namespace: this.deps.namespace,
|
|
308
|
+
chain: op.context.chain,
|
|
309
|
+
network: op.context.network,
|
|
310
|
+
operationId: op.id,
|
|
311
|
+
expected: expected.toString(),
|
|
312
|
+
...(blocking ? { blockingOperationId: blocking.id } : {}),
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
try {
|
|
316
|
+
const writer = await this.#resolved(writes, op);
|
|
317
|
+
await this.deps.engine.reconcileNonces(writer, op, { acquireTimeoutMs: 0 });
|
|
318
|
+
}
|
|
319
|
+
catch (error) {
|
|
320
|
+
const busy = (0, error_1.isCryptoAioError)(error, 'SEQUENCE_BUSY');
|
|
321
|
+
this.deps.log[busy ? 'debug' : 'warn']('nonce reconciliation did not run', {
|
|
322
|
+
operationId: op.id,
|
|
323
|
+
code: (0, engine_rules_1.errorCode)(error),
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
exports.Workers = Workers;
|
|
329
|
+
//# sourceMappingURL=workers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workers.js","sourceRoot":"","sources":["../../../src/core/lifecycle/workers.ts"],"names":[],"mappings":"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","sourcesContent":["import { ConfigError, isCryptoAioError } from '../errors/error';\nimport {\n NON_TERMINAL_STATES,\n isTerminal,\n type Fence,\n type OperationClaim,\n type OperationPatch,\n type OperationRecord,\n} from '../store/types';\nimport { randomId } from '../util/bytes';\nimport type { ReadTarget } from './engine';\nimport { PRE_SIGNING_STATES, errorCode } from './engine-rules';\nimport type { MonitorDeps, ReadResolver, TargetResolver } from './monitor';\n\n/*\n * The monitor's background worker loop and startup recovery (`Monitor` delegates to\n * `Workers`). They check Operations through the monitor\n * (`MonitorChecks`) and write only through the engine.\n */\n\n/**\n * What `recover()` did. The counts are per Operation, except `reconciled`, and they\n * overlap: an Operation whose resend was attempted and whose check then failed counts in\n * both `rebroadcast` and `failed`.\n */\nexport interface RecoveryReport {\n /**\n * `signed` or ambiguously `submitted` Operations whose stored bytes were sent again:\n * attempted resends, including ones the node refused or whose outcome is unknown.\n */\n readonly rebroadcast: number;\n /** Operations checked on chain after any resend. */\n readonly checked: number;\n /** Operations that need a caller (see `recovery.skipped`); never resent or checked. */\n readonly skipped: number;\n /** Operations whose target could not be rebuilt, or whose resend or check threw. */\n readonly failed: number;\n /** Leaked nonce values that reconciliation returned for reuse (across all wallets). */\n readonly reconciled: number;\n}\n\nexport interface WorkerOptions {\n /** Default: a random id per `start` call. */\n readonly workerId?: string;\n readonly signal?: AbortSignal;\n /** How many due Operations one pass claims. Default: 50. */\n readonly batch?: number;\n}\n\nconst DEFAULT_BATCH = 50;\n/** How many Operations' reported gaps a monitor remembers (`nonce.gap` is at-least-once). */\nconst GAP_MEMORY = 10_000;\n\n/** What the worker loop and recovery use of the monitor's own checks. */\nexport interface MonitorChecks {\n checkPass(\n target: ReadTarget,\n op: OperationRecord,\n fence?: Fence,\n signal?: AbortSignal,\n ): Promise<{ readonly record: OperationRecord; readonly stale: boolean }>;\n check(\n target: ReadTarget,\n op: OperationRecord,\n fence?: Fence,\n signal?: AbortSignal,\n ): Promise<OperationRecord>;\n find(ref: string): Promise<OperationRecord | null>;\n}\n\n/** Worker passes and startup recovery for one monitor (see `Monitor`). */\nexport class Workers {\n /**\n * Per Operation, the expected nonces a `nonce.gap` was already emitted for; least\n * recently reported first, capped at `GAP_MEMORY` Operations.\n */\n readonly #gaps = new Map<string, Set<string>>();\n\n constructor(\n private readonly deps: MonitorDeps,\n private readonly monitor: MonitorChecks,\n ) {}\n\n /**\n * One worker pass: claims up to `batch` due Operations, checks each under its claim fence\n * (a stale worker's writes fail), then releases the claim. Every claimed Operation\n * that stays live leaves the pass scheduled a poll interval ahead, including when its\n * check threw, its view was stale or its all-rejected verdict could not run, so no worker\n * claims it again before then. A stale view also skips gap handling and reconciliation.\n * `signal` bounds each check and its lease wait; once it aborts, the Operations not yet\n * checked are only released, still due, for another worker. Returns how many Operations\n * it claimed.\n */\n async runOnce(options: {\n readonly workerId: string;\n readonly batch?: number;\n readonly signal?: AbortSignal;\n }): Promise<number> {\n const { signal } = options;\n if (signal?.aborted) return 0;\n const claimed = await this.deps.stores.operations.claimDue(\n this.deps.namespace,\n options.workerId,\n this.deps.clock.now(),\n this.deps.lifecycle().claimLeaseMs,\n options.batch ?? DEFAULT_BATCH,\n );\n const reads = this.#passResolver(this.deps.resolveRead);\n const writes = this.#passResolver(this.deps.resolveTarget);\n for (const op of claimed) {\n const fence: Fence = { claimToken: (op.claim as OperationClaim).token };\n if (!signal?.aborted) await this.#process(reads, writes, op, fence, signal);\n await this.deps.stores.operations\n .releaseClaim(this.deps.namespace, op.id, fence)\n .catch((error: unknown) =>\n this.deps.log.debug('claim already lost', {\n operationId: op.id,\n code: errorCode(error),\n }),\n );\n }\n return claimed.length;\n }\n\n /** One claimed Operation of a worker pass (see `runOnce`). */\n async #process(\n reads: ReadResolver,\n writes: TargetResolver,\n op: OperationRecord,\n fence: Fence,\n signal: AbortSignal | undefined,\n ): Promise<void> {\n const started = this.deps.clock.now();\n let current: OperationRecord | undefined;\n try {\n const target = await this.#resolved(reads, op);\n const pass = await this.monitor.checkPass(target, op, fence, signal);\n current = pass.record;\n if (!pass.stale) await this.#detectNonceGap(target, current, writes);\n } catch (error) {\n // An abort mid-check is an expected shutdown, not a failure.\n this.deps.log[signal?.aborted ? 'debug' : 'warn'](\n signal?.aborted ? 'monitor check stopped' : 'monitor check failed',\n { operationId: op.id, code: errorCode(error) },\n );\n }\n const scheduled =\n current !== undefined &&\n (isTerminal(current.state) ||\n (current.nextCheckAt !== undefined && current.nextCheckAt > started));\n if (!scheduled) await this.#reschedule(op.id, fence, started);\n }\n\n /**\n * Runs worker passes until `signal` aborts. Any number of workers, in any number of\n * processes, may run: claims keep them apart. A full batch is followed by the next pass at\n * once, anything less by a poll-interval sleep. A failed pass (e.g. a store outage) is\n * logged by code and retried after the sleep.\n */\n async start(options: WorkerOptions = {}): Promise<void> {\n const workerId = options.workerId ?? randomId('worker');\n const batch = options.batch ?? DEFAULT_BATCH;\n const { signal } = options;\n while (!signal?.aborted) {\n let processed = 0;\n try {\n processed = await this.runOnce({\n workerId,\n batch,\n ...(signal ? { signal } : {}),\n });\n } catch (error) {\n this.deps.log.warn('monitor worker pass failed', {\n workerId,\n code: errorCode(error),\n });\n }\n if (processed > 0 && processed >= batch) continue;\n try {\n await this.deps.clock.sleep(this.deps.lifecycle().pollIntervalMs, signal);\n } catch {\n return;\n }\n }\n }\n\n /**\n * Startup recovery for this namespace; it never signs. `signed` and ambiguously\n * `submitted` Operations resend their stored raw bytes; every other signed-or-later live\n * Operation is checked. `created`, `prepared`, `awaiting-signature` and `stalled` ones need\n * a caller and are reported through `recovery.skipped` (codes and states only). Then each\n * wallet with a live Operation has its nonces reconciled under its address lease. A\n * failure is logged by code and counted, and the rest go on. `signal` stops recovery\n * between Operations and bounds each check and lease wait. Known gap: a `signed` or\n * ambiguous Operation whose wallet-bound target cannot be resolved is counted `failed`\n * without its check, although the check needs no wallet.\n */\n async recover(\n options: { readonly signal?: AbortSignal } = {},\n ): Promise<RecoveryReport> {\n const { signal } = options;\n const { namespace } = this.deps;\n const live = await this.deps.stores.operations.list({\n namespace,\n states: NON_TERMINAL_STATES,\n });\n const reads = this.#passResolver(this.deps.resolveRead);\n const writes = this.#passResolver(this.deps.resolveTarget);\n let rebroadcast = 0;\n let checked = 0;\n let skipped = 0;\n let failed = 0;\n let reconciled = 0;\n const skip = (op: OperationRecord, reason: string) => {\n skipped += 1;\n this.deps.events.emit('recovery.skipped', {\n namespace,\n operationId: op.id,\n state: op.state,\n reason,\n });\n };\n for (const op of live) {\n if (signal?.aborted) break;\n if (PRE_SIGNING_STATES.has(op.state)) {\n skip(op, 'CALLER_ACTION_REQUIRED');\n continue;\n }\n if (op.state === 'stalled') {\n skip(op, 'STALLED');\n continue;\n }\n try {\n const target = await this.#resolved(reads, op);\n let current = op;\n if (\n op.state === 'signed' ||\n (op.state === 'submitted' && op.ambiguous === true)\n ) {\n const writer = await this.#resolved(writes, op);\n try {\n current = await this.deps.engine.rebroadcast(writer, op.id, signal);\n } catch (error) {\n // A refusal or an unknown outcome is recorded on the Operation: check it next.\n if (\n !isCryptoAioError(error) ||\n (error.category !== 'chain' && error.ambiguous !== true)\n )\n throw error;\n current = (await this.monitor.find(op.id)) ?? op;\n }\n rebroadcast += 1;\n }\n await this.monitor.check(target, current, undefined, signal);\n checked += 1;\n } catch (error) {\n failed += 1;\n this.deps.log.warn('recovery of an operation failed', {\n operationId: op.id,\n code: errorCode(error),\n });\n }\n }\n const wallets = new Map<string, OperationRecord>();\n for (const op of live) {\n const key = [op.context.chain, op.context.network, op.intent.from].join('\\n');\n if (!wallets.has(key)) wallets.set(key, op);\n }\n for (const op of wallets.values()) {\n if (signal?.aborted) break;\n try {\n const writer = await this.#resolved(writes, op);\n reconciled += (await this.deps.engine.reconcileNonces(writer, op, { signal }))\n .length;\n } catch (error) {\n this.deps.log.warn('nonce reconciliation failed', {\n operationId: op.id,\n code: errorCode(error),\n });\n }\n }\n return { rebroadcast, checked, skipped, failed, reconciled };\n }\n\n /**\n * `resolve` for one pass: each execution context's target is rebuilt at most once, and\n * only when first asked for (a wallet-bound one only by a write that needs it).\n */\n #passResolver<T>(\n resolve: (op: OperationRecord) => Promise<T | undefined>,\n ): (op: OperationRecord) => Promise<T | undefined> {\n const targets = new Map<string, Promise<T | undefined>>();\n return (op) => {\n let target = targets.get(op.context.configHash);\n if (!target) {\n target = resolve(op);\n targets.set(op.context.configHash, target);\n }\n return target;\n };\n }\n\n async #resolved<T>(\n resolve: (op: OperationRecord) => Promise<T | undefined>,\n op: OperationRecord,\n ): Promise<T> {\n const target = await resolve(op);\n if (!target) {\n throw new ConfigError(\n 'CONFIG_INVALID',\n `the target of operation '${op.id}' cannot be rebuilt from its context`,\n );\n }\n return target;\n }\n\n /**\n * Leaves a claimed, live Operation scheduled a poll interval ahead, unless it ended,\n * another worker took it over or a writer scheduled it meanwhile. A pre-signing Operation\n * is never scheduled (callers drive it), so it is unscheduled instead. Best effort.\n */\n async #reschedule(id: string, fence: Fence, started: number): Promise<void> {\n try {\n for (let tries = 0; tries < 3; tries++) {\n const fresh = await this.deps.stores.operations.get(this.deps.namespace, id);\n if (\n !fresh ||\n isTerminal(fresh.state) ||\n fresh.claim?.token !== fence.claimToken ||\n (fresh.nextCheckAt !== undefined && fresh.nextCheckAt > started)\n )\n return;\n const patch: OperationPatch = PRE_SIGNING_STATES.has(fresh.state)\n ? { clear: ['nextCheckAt'] }\n : { nextCheckAt: this.deps.clock.now() + this.deps.lifecycle().pollIntervalMs };\n try {\n await this.deps.engine.update(fresh, patch, fence);\n return;\n } catch (error) {\n if (!isCryptoAioError(error, 'VERSION_CONFLICT')) throw error;\n }\n }\n } catch (error) {\n this.deps.log.debug('could not reschedule a claimed operation', {\n operationId: id,\n code: errorCode(error),\n });\n }\n }\n\n /**\n * `nonce.gap`, once per (Operation, expected nonce): a `submitted` Operation has waited\n * longer than `droppedGracePeriodMs` since its active Attempt was first seen or sent, and\n * the chain's pending nonce is still below its own (a lower nonce is missing\n * even from the mempool, so congestion alone is no gap). It names the live Operation\n * holding the expected nonce, when one exists. Every such pass then reconciles the wallet's nonces, trying the lease\n * once (never a filler transaction): a leaked value goes back for the next transfer.\n * Only that write resolves the wallet-bound target (`writes`).\n */\n async #detectNonceGap(\n target: ReadTarget,\n op: OperationRecord,\n writes: TargetResolver,\n ): Promise<void> {\n const { sequence } = target.pooled.driver;\n if (op.state !== 'submitted' || op.reservation?.kind !== 'nonce' || !sequence) {\n this.#gaps.delete(op.id);\n return;\n }\n const attempt = op.attempts.find((a) => a.id === op.activeAttemptId);\n const observation = attempt\n ? await this.deps.stores.operations.getObservation(attempt.id)\n : null;\n // Not `lastBroadcastAt`, which every resend of a dropped Attempt refreshes.\n const since = observation?.firstSeenAt ?? attempt?.createdAt ?? op.createdAt;\n if (this.deps.clock.now() - since < this.deps.lifecycle().droppedGracePeriodMs)\n return;\n const expected = await sequence.pending(op.intent.from);\n if (expected >= op.reservation.nonce) return;\n const reported = this.#gaps.get(op.id) ?? new Set<string>();\n this.#gaps.delete(op.id);\n this.#gaps.set(op.id, reported);\n if (this.#gaps.size > GAP_MEMORY) {\n const oldest = this.#gaps.keys().next().value;\n if (oldest !== undefined) this.#gaps.delete(oldest);\n }\n if (!reported.has(expected.toString())) {\n reported.add(expected.toString());\n const blocking = (\n await this.deps.stores.operations.list({\n namespace: this.deps.namespace,\n chain: op.context.chain,\n network: op.context.network,\n from: op.intent.from,\n states: NON_TERMINAL_STATES,\n })\n ).find((o) => o.reservation?.kind === 'nonce' && o.reservation.nonce === expected);\n this.deps.events.emit('nonce.gap', {\n namespace: this.deps.namespace,\n chain: op.context.chain,\n network: op.context.network,\n operationId: op.id,\n expected: expected.toString(),\n ...(blocking ? { blockingOperationId: blocking.id } : {}),\n });\n }\n try {\n const writer = await this.#resolved(writes, op);\n await this.deps.engine.reconcileNonces(writer, op, { acquireTimeoutMs: 0 });\n } catch (error) {\n const busy = isCryptoAioError(error, 'SEQUENCE_BUSY');\n this.deps.log[busy ? 'debug' : 'warn']('nonce reconciliation did not run', {\n operationId: op.id,\n code: errorCode(error),\n });\n }\n }\n}\n"]}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export interface NormalizedAddress {
|
|
2
|
+
readonly canonical: string;
|
|
3
|
+
readonly display: string;
|
|
4
|
+
/**
|
|
5
|
+
* Chain-specific meaning of a recipient address. It reaches drivers in
|
|
6
|
+
* `DriverOutput.variant` and is part of the intent hash, so it must hold only JSON scalars
|
|
7
|
+
* (strings, finite numbers, booleans, `null`) under string keys, and should contain only
|
|
8
|
+
* semantic fields that change what the transfer does (for example TON's `bounceable`),
|
|
9
|
+
* never encoding-only choices such as a display alphabet. Omit it, or leave it empty,
|
|
10
|
+
* when the address has no such meaning: an empty variant is no variant.
|
|
11
|
+
*/
|
|
12
|
+
readonly variant?: Readonly<Record<string, unknown>>;
|
|
13
|
+
}
|
|
14
|
+
export type AddressFormatter = (address: NormalizedAddress, options?: Readonly<Record<string, unknown>>) => string;
|
|
15
|
+
/** A chain-bound address. Equality uses `canonical`; `variant` keeps chain-specific meaning. */
|
|
16
|
+
export declare class Address implements NormalizedAddress {
|
|
17
|
+
#private;
|
|
18
|
+
readonly chain: string;
|
|
19
|
+
readonly canonical: string;
|
|
20
|
+
readonly display: string;
|
|
21
|
+
readonly variant?: Readonly<Record<string, unknown>>;
|
|
22
|
+
constructor(chain: string, normalized: NormalizedAddress, format?: AddressFormatter);
|
|
23
|
+
format(options?: Readonly<Record<string, unknown>>): string;
|
|
24
|
+
equals(other: Address | NormalizedAddress | string): boolean;
|
|
25
|
+
toString(): string;
|
|
26
|
+
toJSON(): {
|
|
27
|
+
chain: string;
|
|
28
|
+
canonical: string;
|
|
29
|
+
display: string;
|
|
30
|
+
variant?: Readonly<Record<string, unknown>>;
|
|
31
|
+
};
|
|
32
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Address = void 0;
|
|
4
|
+
/** A chain-bound address. Equality uses `canonical`; `variant` keeps chain-specific meaning. */
|
|
5
|
+
class Address {
|
|
6
|
+
chain;
|
|
7
|
+
canonical;
|
|
8
|
+
display;
|
|
9
|
+
variant;
|
|
10
|
+
#format;
|
|
11
|
+
constructor(chain, normalized, format) {
|
|
12
|
+
this.chain = chain;
|
|
13
|
+
this.canonical = normalized.canonical;
|
|
14
|
+
this.display = normalized.display;
|
|
15
|
+
if (normalized.variant)
|
|
16
|
+
this.variant = Object.freeze({ ...normalized.variant });
|
|
17
|
+
this.#format = format;
|
|
18
|
+
Object.freeze(this);
|
|
19
|
+
}
|
|
20
|
+
format(options) {
|
|
21
|
+
return this.#format ? this.#format(this, options) : this.display;
|
|
22
|
+
}
|
|
23
|
+
equals(other) {
|
|
24
|
+
if (typeof other === 'string')
|
|
25
|
+
return other === this.canonical;
|
|
26
|
+
if (other instanceof Address && other.chain !== this.chain)
|
|
27
|
+
return false;
|
|
28
|
+
return other.canonical === this.canonical;
|
|
29
|
+
}
|
|
30
|
+
toString() {
|
|
31
|
+
return this.display;
|
|
32
|
+
}
|
|
33
|
+
toJSON() {
|
|
34
|
+
return {
|
|
35
|
+
chain: this.chain,
|
|
36
|
+
canonical: this.canonical,
|
|
37
|
+
display: this.display,
|
|
38
|
+
...(this.variant ? { variant: this.variant } : {}),
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
exports.Address = Address;
|
|
43
|
+
//# sourceMappingURL=address.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"address.js","sourceRoot":"","sources":["../../../src/core/model/address.ts"],"names":[],"mappings":";;;AAmBA,gGAAgG;AAChG,MAAa,OAAO;IACT,KAAK,CAAS;IACd,SAAS,CAAS;IAClB,OAAO,CAAS;IAChB,OAAO,CAAqC;IAC5C,OAAO,CAAoB;IAEpC,YAAY,KAAa,EAAE,UAA6B,EAAE,MAAyB;QACjF,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,SAAS,GAAG,UAAU,CAAC,SAAS,CAAC;QACtC,IAAI,CAAC,OAAO,GAAG,UAAU,CAAC,OAAO,CAAC;QAClC,IAAI,UAAU,CAAC,OAAO;YAAE,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC;QAChF,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;QACtB,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACtB,CAAC;IAED,MAAM,CAAC,OAA2C;QAChD,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC;IACnE,CAAC;IAED,MAAM,CAAC,KAA2C;QAChD,IAAI,OAAO,KAAK,KAAK,QAAQ;YAAE,OAAO,KAAK,KAAK,IAAI,CAAC,SAAS,CAAC;QAC/D,IAAI,KAAK,YAAY,OAAO,IAAI,KAAK,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK;YAAE,OAAO,KAAK,CAAC;QACzE,OAAO,KAAK,CAAC,SAAS,KAAK,IAAI,CAAC,SAAS,CAAC;IAC5C,CAAC;IAED,QAAQ;QACN,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED,MAAM;QAMJ,OAAO;YACL,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACnD,CAAC;IACJ,CAAC;CACF;AA3CD,0BA2CC","sourcesContent":["export interface NormalizedAddress {\n readonly canonical: string;\n readonly display: string;\n /**\n * Chain-specific meaning of a recipient address. It reaches drivers in\n * `DriverOutput.variant` and is part of the intent hash, so it must hold only JSON scalars\n * (strings, finite numbers, booleans, `null`) under string keys, and should contain only\n * semantic fields that change what the transfer does (for example TON's `bounceable`),\n * never encoding-only choices such as a display alphabet. Omit it, or leave it empty,\n * when the address has no such meaning: an empty variant is no variant.\n */\n readonly variant?: Readonly<Record<string, unknown>>;\n}\n\nexport type AddressFormatter = (\n address: NormalizedAddress,\n options?: Readonly<Record<string, unknown>>,\n) => string;\n\n/** A chain-bound address. Equality uses `canonical`; `variant` keeps chain-specific meaning. */\nexport class Address implements NormalizedAddress {\n readonly chain: string;\n readonly canonical: string;\n readonly display: string;\n readonly variant?: Readonly<Record<string, unknown>>;\n readonly #format?: AddressFormatter;\n\n constructor(chain: string, normalized: NormalizedAddress, format?: AddressFormatter) {\n this.chain = chain;\n this.canonical = normalized.canonical;\n this.display = normalized.display;\n if (normalized.variant) this.variant = Object.freeze({ ...normalized.variant });\n this.#format = format;\n Object.freeze(this);\n }\n\n format(options?: Readonly<Record<string, unknown>>): string {\n return this.#format ? this.#format(this, options) : this.display;\n }\n\n equals(other: Address | NormalizedAddress | string): boolean {\n if (typeof other === 'string') return other === this.canonical;\n if (other instanceof Address && other.chain !== this.chain) return false;\n return other.canonical === this.canonical;\n }\n\n toString(): string {\n return this.display;\n }\n\n toJSON(): {\n chain: string;\n canonical: string;\n display: string;\n variant?: Readonly<Record<string, unknown>>;\n } {\n return {\n chain: this.chain,\n canonical: this.canonical,\n display: this.display,\n ...(this.variant ? { variant: this.variant } : {}),\n };\n }\n}\n"]}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { AssetId, AssetInfo } from './asset';
|
|
2
|
+
export type AmountInput = bigint | string | Amount;
|
|
3
|
+
/** An exact, non-negative quantity of one asset in base units. Never floating point. */
|
|
4
|
+
export declare class Amount {
|
|
5
|
+
readonly base: bigint;
|
|
6
|
+
readonly asset: AssetInfo;
|
|
7
|
+
private constructor();
|
|
8
|
+
static fromBase(base: bigint, asset: AssetInfo): Amount;
|
|
9
|
+
static parse(value: string, asset: AssetInfo): Amount;
|
|
10
|
+
static from(input: unknown, asset: AssetInfo): Amount;
|
|
11
|
+
get decimals(): number;
|
|
12
|
+
isZero(): boolean;
|
|
13
|
+
toDecimalString(): string;
|
|
14
|
+
format(): string;
|
|
15
|
+
plus(other: Amount): Amount;
|
|
16
|
+
minus(other: Amount): Amount;
|
|
17
|
+
compare(other: Amount): -1 | 0 | 1;
|
|
18
|
+
equals(other: Amount): boolean;
|
|
19
|
+
toJSON(): {
|
|
20
|
+
base: string;
|
|
21
|
+
asset: AssetId;
|
|
22
|
+
};
|
|
23
|
+
toString(): string;
|
|
24
|
+
private assertSameAsset;
|
|
25
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Amount = void 0;
|
|
4
|
+
const error_1 = require("../errors/error");
|
|
5
|
+
const DECIMAL = /^(0|[1-9][0-9]*)(\.[0-9]+)?$/;
|
|
6
|
+
function invalid(message) {
|
|
7
|
+
return new error_1.ValidationError('INVALID_AMOUNT', message);
|
|
8
|
+
}
|
|
9
|
+
/** An exact, non-negative quantity of one asset in base units. Never floating point. */
|
|
10
|
+
class Amount {
|
|
11
|
+
base;
|
|
12
|
+
asset;
|
|
13
|
+
constructor(base, asset) {
|
|
14
|
+
this.base = base;
|
|
15
|
+
this.asset = asset;
|
|
16
|
+
Object.freeze(this);
|
|
17
|
+
}
|
|
18
|
+
static fromBase(base, asset) {
|
|
19
|
+
if (typeof base !== 'bigint')
|
|
20
|
+
throw invalid('base amount must be a bigint');
|
|
21
|
+
if (base < 0n)
|
|
22
|
+
throw invalid('amounts cannot be negative');
|
|
23
|
+
return new Amount(base, asset);
|
|
24
|
+
}
|
|
25
|
+
static parse(value, asset) {
|
|
26
|
+
if (typeof value !== 'string' || !DECIMAL.test(value)) {
|
|
27
|
+
throw invalid(`'${String(value)}' is not a plain decimal string (expected digits with an optional fractional part, e.g. "1.25")`);
|
|
28
|
+
}
|
|
29
|
+
const { decimals, symbol } = asset.metadata;
|
|
30
|
+
const [whole = '0', fraction = ''] = value.split('.');
|
|
31
|
+
if (fraction.length > decimals) {
|
|
32
|
+
throw invalid(`'${value}' has ${fraction.length} fractional digits but ${symbol} has ${decimals} decimals`);
|
|
33
|
+
}
|
|
34
|
+
const scale = 10n ** BigInt(decimals);
|
|
35
|
+
const fractional = fraction.length > 0 ? BigInt(fraction.padEnd(decimals, '0')) : 0n;
|
|
36
|
+
return new Amount(BigInt(whole) * scale + fractional, asset);
|
|
37
|
+
}
|
|
38
|
+
static from(input, asset) {
|
|
39
|
+
if (input instanceof Amount) {
|
|
40
|
+
if (input.asset.id !== asset.id) {
|
|
41
|
+
throw invalid(`amount is denominated in '${input.asset.id}', expected '${asset.id}'`);
|
|
42
|
+
}
|
|
43
|
+
return input;
|
|
44
|
+
}
|
|
45
|
+
if (typeof input === 'bigint')
|
|
46
|
+
return Amount.fromBase(input, asset);
|
|
47
|
+
if (typeof input === 'string')
|
|
48
|
+
return Amount.parse(input, asset);
|
|
49
|
+
if (typeof input === 'number') {
|
|
50
|
+
throw invalid('JavaScript numbers are not accepted for amounts; use a bigint (base units) or a decimal string');
|
|
51
|
+
}
|
|
52
|
+
throw invalid(`unsupported amount input of type ${input === null ? 'null' : typeof input}`);
|
|
53
|
+
}
|
|
54
|
+
get decimals() {
|
|
55
|
+
return this.asset.metadata.decimals;
|
|
56
|
+
}
|
|
57
|
+
isZero() {
|
|
58
|
+
return this.base === 0n;
|
|
59
|
+
}
|
|
60
|
+
toDecimalString() {
|
|
61
|
+
const decimals = this.decimals;
|
|
62
|
+
if (decimals === 0)
|
|
63
|
+
return this.base.toString();
|
|
64
|
+
const digits = this.base.toString().padStart(decimals + 1, '0');
|
|
65
|
+
const whole = digits.slice(0, -decimals);
|
|
66
|
+
const fraction = digits.slice(-decimals).replace(/0+$/, '');
|
|
67
|
+
return fraction ? `${whole}.${fraction}` : whole;
|
|
68
|
+
}
|
|
69
|
+
format() {
|
|
70
|
+
return `${this.toDecimalString()} ${this.asset.metadata.symbol}`;
|
|
71
|
+
}
|
|
72
|
+
plus(other) {
|
|
73
|
+
this.assertSameAsset(other);
|
|
74
|
+
return new Amount(this.base + other.base, this.asset);
|
|
75
|
+
}
|
|
76
|
+
minus(other) {
|
|
77
|
+
this.assertSameAsset(other);
|
|
78
|
+
if (other.base > this.base)
|
|
79
|
+
throw invalid('result would be negative');
|
|
80
|
+
return new Amount(this.base - other.base, this.asset);
|
|
81
|
+
}
|
|
82
|
+
compare(other) {
|
|
83
|
+
this.assertSameAsset(other);
|
|
84
|
+
return this.base < other.base ? -1 : this.base > other.base ? 1 : 0;
|
|
85
|
+
}
|
|
86
|
+
equals(other) {
|
|
87
|
+
return other.asset.id === this.asset.id && other.base === this.base;
|
|
88
|
+
}
|
|
89
|
+
toJSON() {
|
|
90
|
+
return { base: this.base.toString(), asset: this.asset.id };
|
|
91
|
+
}
|
|
92
|
+
toString() {
|
|
93
|
+
return this.format();
|
|
94
|
+
}
|
|
95
|
+
assertSameAsset(other) {
|
|
96
|
+
if (other.asset.id !== this.asset.id) {
|
|
97
|
+
throw invalid(`cannot combine '${this.asset.id}' with '${other.asset.id}'`);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
exports.Amount = Amount;
|
|
102
|
+
//# sourceMappingURL=amount.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"amount.js","sourceRoot":"","sources":["../../../src/core/model/amount.ts"],"names":[],"mappings":"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","sourcesContent":["import { ValidationError } from '../errors/error';\nimport type { AssetId, AssetInfo } from './asset';\n\nexport type AmountInput = bigint | string | Amount;\n\nconst DECIMAL = /^(0|[1-9][0-9]*)(\\.[0-9]+)?$/;\n\nfunction invalid(message: string): ValidationError {\n return new ValidationError('INVALID_AMOUNT', message);\n}\n\n/** An exact, non-negative quantity of one asset in base units. Never floating point. */\nexport class Amount {\n private constructor(\n readonly base: bigint,\n readonly asset: AssetInfo,\n ) {\n Object.freeze(this);\n }\n\n static fromBase(base: bigint, asset: AssetInfo): Amount {\n if (typeof base !== 'bigint') throw invalid('base amount must be a bigint');\n if (base < 0n) throw invalid('amounts cannot be negative');\n return new Amount(base, asset);\n }\n\n static parse(value: string, asset: AssetInfo): Amount {\n if (typeof value !== 'string' || !DECIMAL.test(value)) {\n throw invalid(\n `'${String(value)}' is not a plain decimal string (expected digits with an optional fractional part, e.g. \"1.25\")`,\n );\n }\n const { decimals, symbol } = asset.metadata;\n const [whole = '0', fraction = ''] = value.split('.');\n if (fraction.length > decimals) {\n throw invalid(\n `'${value}' has ${fraction.length} fractional digits but ${symbol} has ${decimals} decimals`,\n );\n }\n const scale = 10n ** BigInt(decimals);\n const fractional = fraction.length > 0 ? BigInt(fraction.padEnd(decimals, '0')) : 0n;\n return new Amount(BigInt(whole) * scale + fractional, asset);\n }\n\n static from(input: unknown, asset: AssetInfo): Amount {\n if (input instanceof Amount) {\n if (input.asset.id !== asset.id) {\n throw invalid(\n `amount is denominated in '${input.asset.id}', expected '${asset.id}'`,\n );\n }\n return input;\n }\n if (typeof input === 'bigint') return Amount.fromBase(input, asset);\n if (typeof input === 'string') return Amount.parse(input, asset);\n if (typeof input === 'number') {\n throw invalid(\n 'JavaScript numbers are not accepted for amounts; use a bigint (base units) or a decimal string',\n );\n }\n throw invalid(\n `unsupported amount input of type ${input === null ? 'null' : typeof input}`,\n );\n }\n\n get decimals(): number {\n return this.asset.metadata.decimals;\n }\n\n isZero(): boolean {\n return this.base === 0n;\n }\n\n toDecimalString(): string {\n const decimals = this.decimals;\n if (decimals === 0) return this.base.toString();\n const digits = this.base.toString().padStart(decimals + 1, '0');\n const whole = digits.slice(0, -decimals);\n const fraction = digits.slice(-decimals).replace(/0+$/, '');\n return fraction ? `${whole}.${fraction}` : whole;\n }\n\n format(): string {\n return `${this.toDecimalString()} ${this.asset.metadata.symbol}`;\n }\n\n plus(other: Amount): Amount {\n this.assertSameAsset(other);\n return new Amount(this.base + other.base, this.asset);\n }\n\n minus(other: Amount): Amount {\n this.assertSameAsset(other);\n if (other.base > this.base) throw invalid('result would be negative');\n return new Amount(this.base - other.base, this.asset);\n }\n\n compare(other: Amount): -1 | 0 | 1 {\n this.assertSameAsset(other);\n return this.base < other.base ? -1 : this.base > other.base ? 1 : 0;\n }\n\n equals(other: Amount): boolean {\n return other.asset.id === this.asset.id && other.base === this.base;\n }\n\n toJSON(): { base: string; asset: AssetId } {\n return { base: this.base.toString(), asset: this.asset.id };\n }\n\n toString(): string {\n return this.format();\n }\n\n private assertSameAsset(other: Amount): void {\n if (other.asset.id !== this.asset.id) {\n throw invalid(`cannot combine '${this.asset.id}' with '${other.asset.id}'`);\n }\n }\n}\n"]}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export type AssetRef = 'native' | {
|
|
2
|
+
readonly standard: string;
|
|
3
|
+
readonly contract: string;
|
|
4
|
+
};
|
|
5
|
+
export type TokenRef = Exclude<AssetRef, 'native'>;
|
|
6
|
+
export type AssetId = string;
|
|
7
|
+
export interface AssetMetadata {
|
|
8
|
+
readonly symbol: string;
|
|
9
|
+
readonly decimals: number;
|
|
10
|
+
readonly name?: string;
|
|
11
|
+
}
|
|
12
|
+
export interface AssetInfo {
|
|
13
|
+
readonly id: AssetId;
|
|
14
|
+
readonly chain: string;
|
|
15
|
+
readonly network: string;
|
|
16
|
+
readonly ref: AssetRef;
|
|
17
|
+
readonly metadata: AssetMetadata;
|
|
18
|
+
}
|
|
19
|
+
export declare function assetId(chain: string, network: string, ref: AssetRef): AssetId;
|
|
20
|
+
export declare function isAssetId(value: string): boolean;
|
|
21
|
+
export declare function parseAssetId(id: string): {
|
|
22
|
+
chain: string;
|
|
23
|
+
network: string;
|
|
24
|
+
ref: AssetRef;
|
|
25
|
+
};
|
|
26
|
+
export declare function sameAssetRef(a: AssetRef, b: AssetRef): boolean;
|
|
27
|
+
/** Returns a reason when metadata is unusable, otherwise `undefined`. */
|
|
28
|
+
export declare function metadataProblem(metadata: AssetMetadata): string | undefined;
|